| //[ MapAssign |
| // Copyright 2008 Eric Niebler. 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) |
| // |
| // This is a port of map_list_of() from the Boost.Assign library. |
| // It has the advantage of being more efficient at runtime by not |
| // building any temporary container that requires dynamic allocation. |
| |
| #include <map> |
| #include <string> |
| #include <iostream> |
| #include <boost/proto/core.hpp> |
| #include <boost/proto/transform.hpp> |
| #include <boost/type_traits/add_reference.hpp> |
| namespace proto = boost::proto; |
| using proto::_; |
| |
| struct map_list_of_tag |
| {}; |
| |
| // A simple callable function object that inserts a |
| // (key,value) pair into a map. |
| struct insert |
| : proto::callable |
| { |
| template<typename Sig> |
| struct result; |
| |
| template<typename This, typename Map, typename Key, typename Value> |
| struct result<This(Map, Key, Value)> |
| : boost::add_reference<Map> |
| {}; |
| |
| template<typename Map, typename Key, typename Value> |
| Map &operator()(Map &map, Key const &key, Value const &value) const |
| { |
| map.insert(typename Map::value_type(key, value)); |
| return map; |
| } |
| }; |
| |
| // Work-arounds for Microsoft Visual C++ 7.1 |
| #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) |
| #define MapListOf(x) proto::call<MapListOf(x)> |
| #define _value(x) call<proto::_value(x)> |
| #endif |
| |
| // The grammar for valid map-list expressions, and a |
| // transform that populates the map. |
| struct MapListOf |
| : proto::or_< |
| proto::when< |
| proto::function< |
| proto::terminal<map_list_of_tag> |
| , proto::terminal<_> |
| , proto::terminal<_> |
| > |
| , insert( |
| proto::_data |
| , proto::_value(proto::_child1) |
| , proto::_value(proto::_child2) |
| ) |
| > |
| , proto::when< |
| proto::function< |
| MapListOf |
| , proto::terminal<_> |
| , proto::terminal<_> |
| > |
| , insert( |
| MapListOf(proto::_child0) |
| , proto::_value(proto::_child1) |
| , proto::_value(proto::_child2) |
| ) |
| > |
| > |
| {}; |
| |
| #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) |
| #undef MapListOf |
| #undef _value |
| #endif |
| |
| template<typename Expr> |
| struct map_list_of_expr; |
| |
| struct map_list_of_dom |
| : proto::domain<proto::pod_generator<map_list_of_expr>, MapListOf> |
| {}; |
| |
| // An expression wrapper that provides a conversion to a |
| // map that uses the MapListOf |
| template<typename Expr> |
| struct map_list_of_expr |
| { |
| BOOST_PROTO_BASIC_EXTENDS(Expr, map_list_of_expr, map_list_of_dom) |
| BOOST_PROTO_EXTENDS_FUNCTION() |
| |
| template<typename Key, typename Value, typename Cmp, typename Al> |
| operator std::map<Key, Value, Cmp, Al> () const |
| { |
| BOOST_MPL_ASSERT((proto::matches<Expr, MapListOf>)); |
| std::map<Key, Value, Cmp, Al> map; |
| return MapListOf()(*this, 0, map); |
| } |
| }; |
| |
| map_list_of_expr<proto::terminal<map_list_of_tag>::type> const map_list_of = {{{}}}; |
| |
| int main() |
| { |
| // Initialize a map: |
| std::map<std::string, int> op = |
| map_list_of |
| ("<", 1) |
| ("<=",2) |
| (">", 3) |
| (">=",4) |
| ("=", 5) |
| ("<>",6) |
| ; |
| |
| 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; |
| } |
| //] |
| |