// Copyright (C) 2016-2018 T. Zachary Laine // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include <boost/yap/expression.hpp> #include <boost/assign/list_of.hpp> #include <map> #include <iostream> template<typename Key, typename Value, typename Allocator> struct map_list_of_transform { template<typename Fn, typename Key2, typename Value2> auto operator()( boost::yap::expr_tag<boost::yap::expr_kind::call>, Fn const & fn, Key2 && key, Value2 && value) { boost::yap::transform( boost::yap::as_expr<boost::yap::minimal_expr>(fn), *this); map.emplace( Key{std::forward<Key2 &&>(key)}, Value{std::forward<Value2 &&>(value)}); return 0; } std::map<Key, Value, Allocator> map; }; template<boost::yap::expr_kind Kind, typename Tuple> struct map_list_of_expr { static boost::yap::expr_kind const kind = Kind; Tuple elements; template<typename Key, typename Value, typename Allocator> operator std::map<Key, Value, Allocator>() const { map_list_of_transform<Key, Value, Allocator> transform; boost::yap::transform(*this, transform); return transform.map; } BOOST_YAP_USER_CALL_OPERATOR(::map_list_of_expr) }; struct map_list_of_tag {}; auto map_list_of = boost::yap::make_terminal<map_list_of_expr>(map_list_of_tag{}); #if __GNUC__ || __clang__ #define NOINLINE __attribute__((noinline)) #else #define NOINLINE #endif NOINLINE std::map<std::string, int> make_map_with_boost_yap() { return map_list_of("<", 1)("<=", 2)(">", 3)(">=", 4)("=", 5)("<>", 6); } NOINLINE std::map<std::string, int> make_map_with_boost_assign() { return boost::assign::map_list_of("<", 1)("<=", 2)(">", 3)(">=", 4)("=", 5)( "<>", 6); } NOINLINE std::map<std::string, int> make_map_manually() { std::map<std::string, int> retval; retval.emplace("<", 1); retval.emplace("<=", 2); retval.emplace(">", 3); retval.emplace(">=", 4); retval.emplace("=", 5); retval.emplace("<>", 6); return retval; } NOINLINE std::map<std::string, int> make_map_inializer_list() { std::map<std::string, int> retval = { {"<", 1}, {"<=", 2}, {">", 3}, {">=", 4}, {"=", 5}, {"<>", 6}}; return retval; } int main() { { std::map<std::string, int> op = make_map_with_boost_yap(); std::cout << "\"<\" --> " << op["<"] << std::endl; std::cout << "\"<=\" --> " << op["<="] << std::endl; std::cout << "\">\" --> " << op[">"] << std::endl; std::cout << "\">=\" --> " << op[">="] << std::endl; std::cout << "\"=\" --> " << op["="] << std::endl; std::cout << "\"<>\" --> " << op["<>"] << std::endl; } { std::map<std::string, int> op = make_map_with_boost_assign(); std::cout << "\"<\" --> " << op["<"] << std::endl; std::cout << "\"<=\" --> " << op["<="] << std::endl; std::cout << "\">\" --> " << op[">"] << std::endl; std::cout << "\">=\" --> " << op[">="] << std::endl; std::cout << "\"=\" --> " << op["="] << std::endl; std::cout << "\"<>\" --> " << op["<>"] << std::endl; } { std::map<std::string, int> op = make_map_manually(); std::cout << "\"<\" --> " << op["<"] << std::endl; std::cout << "\"<=\" --> " << op["<="] << std::endl; std::cout << "\">\" --> " << op[">"] << std::endl; std::cout << "\">=\" --> " << op[">="] << std::endl; std::cout << "\"=\" --> " << op["="] << std::endl; std::cout << "\"<>\" --> " << op["<>"] << std::endl; } { std::map<std::string, int> op = make_map_inializer_list(); std::cout << "\"<\" --> " << op["<"] << std::endl; std::cout << "\"<=\" --> " << op["<="] << std::endl; std::cout << "\">\" --> " << op[">"] << std::endl; std::cout << "\">=\" --> " << op[">="] << std::endl; std::cout << "\"=\" --> " << op["="] << std::endl; std::cout << "\"<>\" --> " << op["<>"] << std::endl; } return 0; }