map_assign.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. #include <map>
  10. #include <string>
  11. #include <iostream>
  12. #include <boost/proto/core.hpp>
  13. #include <boost/proto/transform.hpp>
  14. #include <boost/type_traits/add_reference.hpp>
  15. namespace proto = boost::proto;
  16. using proto::_;
  17. struct map_list_of_tag
  18. {};
  19. // A simple callable function object that inserts a
  20. // (key,value) pair into a map.
  21. struct insert
  22. : proto::callable
  23. {
  24. template<typename Sig>
  25. struct result;
  26. template<typename This, typename Map, typename Key, typename Value>
  27. struct result<This(Map, Key, Value)>
  28. : boost::add_reference<Map>
  29. {};
  30. template<typename Map, typename Key, typename Value>
  31. Map &operator()(Map &map, Key const &key, Value const &value) const
  32. {
  33. map.insert(typename Map::value_type(key, value));
  34. return map;
  35. }
  36. };
  37. // Work-arounds for Microsoft Visual C++ 7.1
  38. #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  39. #define MapListOf(x) proto::call<MapListOf(x)>
  40. #define _value(x) call<proto::_value(x)>
  41. #endif
  42. // The grammar for valid map-list expressions, and a
  43. // transform that populates the map.
  44. struct MapListOf
  45. : proto::or_<
  46. proto::when<
  47. // map_list_of(a,b)
  48. proto::function<
  49. proto::terminal<map_list_of_tag>
  50. , proto::terminal<_>
  51. , proto::terminal<_>
  52. >
  53. , insert(
  54. proto::_data
  55. , proto::_value(proto::_child1)
  56. , proto::_value(proto::_child2)
  57. )
  58. >
  59. , proto::when<
  60. // map_list_of(a,b)(c,d)...
  61. proto::function<
  62. MapListOf
  63. , proto::terminal<_>
  64. , proto::terminal<_>
  65. >
  66. , insert(
  67. MapListOf(proto::_child0)
  68. , proto::_value(proto::_child1)
  69. , proto::_value(proto::_child2)
  70. )
  71. >
  72. >
  73. {};
  74. #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
  75. #undef MapListOf
  76. #undef _value
  77. #endif
  78. template<typename Expr>
  79. struct map_list_of_expr;
  80. struct map_list_of_dom
  81. : proto::domain<proto::pod_generator<map_list_of_expr>, MapListOf>
  82. {};
  83. // An expression wrapper that provides a conversion to a
  84. // map that uses the MapListOf
  85. template<typename Expr>
  86. struct map_list_of_expr
  87. {
  88. BOOST_PROTO_BASIC_EXTENDS(Expr, map_list_of_expr, map_list_of_dom)
  89. BOOST_PROTO_EXTENDS_FUNCTION()
  90. template<typename Key, typename Value, typename Cmp, typename Al>
  91. operator std::map<Key, Value, Cmp, Al> () const
  92. {
  93. BOOST_MPL_ASSERT((proto::matches<Expr, MapListOf>));
  94. std::map<Key, Value, Cmp, Al> map;
  95. return MapListOf()(*this, 0, map);
  96. }
  97. };
  98. map_list_of_expr<proto::terminal<map_list_of_tag>::type> const map_list_of = {{{}}};
  99. int main()
  100. {
  101. // Initialize a map:
  102. std::map<std::string, int> op =
  103. map_list_of
  104. ("<", 1)
  105. ("<=",2)
  106. (">", 3)
  107. (">=",4)
  108. ("=", 5)
  109. ("<>",6)
  110. ;
  111. std::cout << "\"<\" --> " << op["<"] << std::endl;
  112. std::cout << "\"<=\" --> " << op["<="] << std::endl;
  113. std::cout << "\">\" --> " << op[">"] << std::endl;
  114. std::cout << "\">=\" --> " << op[">="] << std::endl;
  115. std::cout << "\"=\" --> " << op["="] << std::endl;
  116. std::cout << "\"<>\" --> " << op["<>"] << std::endl;
  117. return 0;
  118. }
  119. //]