• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //[ MapAssign
2 //  Copyright 2008 Eric Niebler. Distributed under the Boost
3 //  Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 //
6 // This is a port of map_list_of() from the Boost.Assign library.
7 // It has the advantage of being more efficient at runtime by not
8 // building any temporary container that requires dynamic allocation.
9 
10 #include <map>
11 #include <string>
12 #include <iostream>
13 #include <boost/proto/core.hpp>
14 #include <boost/proto/transform.hpp>
15 #include <boost/type_traits/add_reference.hpp>
16 namespace proto = boost::proto;
17 using proto::_;
18 
19 struct map_list_of_tag
20 {};
21 
22 // A simple callable function object that inserts a
23 // (key,value) pair into a map.
24 struct insert
25   : proto::callable
26 {
27     template<typename Sig>
28     struct result;
29 
30     template<typename This, typename Map, typename Key, typename Value>
31     struct result<This(Map, Key, Value)>
32       : boost::add_reference<Map>
33     {};
34 
35     template<typename Map, typename Key, typename Value>
operator ()insert36     Map &operator()(Map &map, Key const &key, Value const &value) const
37     {
38         map.insert(typename Map::value_type(key, value));
39         return map;
40     }
41 };
42 
43 // Work-arounds for Microsoft Visual C++ 7.1
44 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
45 #define MapListOf(x) proto::call<MapListOf(x)>
46 #define _value(x) call<proto::_value(x)>
47 #endif
48 
49 // The grammar for valid map-list expressions, and a
50 // transform that populates the map.
51 struct MapListOf
52   : proto::or_<
53         proto::when<
54             // map_list_of(a,b)
55             proto::function<
56                 proto::terminal<map_list_of_tag>
57               , proto::terminal<_>
58               , proto::terminal<_>
59             >
60           , insert(
61                 proto::_data
62               , proto::_value(proto::_child1)
63               , proto::_value(proto::_child2)
64             )
65         >
66       , proto::when<
67             // map_list_of(a,b)(c,d)...
68             proto::function<
69                 MapListOf
70               , proto::terminal<_>
71               , proto::terminal<_>
72             >
73           , insert(
74                 MapListOf(proto::_child0)
75               , proto::_value(proto::_child1)
76               , proto::_value(proto::_child2)
77             )
78         >
79     >
80 {};
81 
82 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
83 #undef MapListOf
84 #undef _value
85 #endif
86 
87 template<typename Expr>
88 struct map_list_of_expr;
89 
90 struct map_list_of_dom
91   : proto::domain<proto::pod_generator<map_list_of_expr>, MapListOf>
92 {};
93 
94 // An expression wrapper that provides a conversion to a
95 // map that uses the MapListOf
96 template<typename Expr>
97 struct map_list_of_expr
98 {
BOOST_PROTO_BASIC_EXTENDSmap_list_of_expr99     BOOST_PROTO_BASIC_EXTENDS(Expr, map_list_of_expr, map_list_of_dom)
100     BOOST_PROTO_EXTENDS_FUNCTION()
101 
102     template<typename Key, typename Value, typename Cmp, typename Al>
103     operator std::map<Key, Value, Cmp, Al> () const
104     {
105         BOOST_MPL_ASSERT((proto::matches<Expr, MapListOf>));
106         std::map<Key, Value, Cmp, Al> map;
107         return MapListOf()(*this, 0, map);
108     }
109 };
110 
111 map_list_of_expr<proto::terminal<map_list_of_tag>::type> const map_list_of = {{{}}};
112 
main()113 int main()
114 {
115     // Initialize a map:
116     std::map<std::string, int> op =
117         map_list_of
118             ("<", 1)
119             ("<=",2)
120             (">", 3)
121             (">=",4)
122             ("=", 5)
123             ("<>",6)
124         ;
125 
126     std::cout << "\"<\"  --> " << op["<"] << std::endl;
127     std::cout << "\"<=\" --> " << op["<="] << std::endl;
128     std::cout << "\">\"  --> " << op[">"] << std::endl;
129     std::cout << "\">=\" --> " << op[">="] << std::endl;
130     std::cout << "\"=\"  --> " << op["="] << std::endl;
131     std::cout << "\"<>\" --> " << op["<>"] << std::endl;
132 
133     return 0;
134 }
135 //]
136 
137