modify.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. http://spirit.sourceforge.net/
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. #ifndef BOOST_SPIRIT_MODIFY_OCTOBER_25_2008_0142PM
  8. #define BOOST_SPIRIT_MODIFY_OCTOBER_25_2008_0142PM
  9. #if defined(_MSC_VER)
  10. #pragma once
  11. #endif
  12. #include <boost/spirit/include/phoenix_limits.hpp> // needs to be included before proto
  13. #include <boost/proto/proto.hpp>
  14. #include <boost/mpl/if.hpp>
  15. #include <boost/type_traits/is_base_of.hpp>
  16. #include <boost/spirit/home/support/unused.hpp>
  17. namespace boost { namespace spirit
  18. {
  19. template <typename Domain, typename T, typename Enable = void>
  20. struct is_modifier_directive;
  21. // Testing if a modifier set includes a modifier T involves
  22. // checking for inheritance (i.e. Modifiers is derived from T)
  23. template <typename Modifiers, typename T>
  24. struct has_modifier
  25. : is_base_of<T, Modifiers> {};
  26. // Adding modifiers is done using multi-inheritance
  27. template <typename Current, typename New, typename Enable = void>
  28. struct compound_modifier : Current, New
  29. {
  30. compound_modifier()
  31. : Current(), New() {}
  32. compound_modifier(Current const& current, New const& new_)
  33. : Current(current), New(new_) {}
  34. };
  35. // Don't add if New is already in Current
  36. template <typename Current, typename New>
  37. struct compound_modifier<
  38. Current, New, typename enable_if<has_modifier<Current, New> >::type>
  39. : Current
  40. {
  41. compound_modifier()
  42. : Current() {}
  43. compound_modifier(Current const& current, New const&)
  44. : Current(current) {}
  45. };
  46. // Special case if Current is unused_type
  47. template <typename New, typename Enable>
  48. struct compound_modifier<unused_type, New, Enable> : New
  49. {
  50. compound_modifier()
  51. : New() {}
  52. compound_modifier(unused_type, New const& new_)
  53. : New(new_) {}
  54. };
  55. // Domains may specialize this modify metafunction to allow
  56. // directives to add information to the Modifier template
  57. // parameter that is passed to the make_component metafunction.
  58. // By default, we return the modifiers untouched
  59. template <typename Domain, typename Enable = void>
  60. struct modify
  61. {
  62. template <typename Sig>
  63. struct result;
  64. template <typename This, typename Tag, typename Modifiers>
  65. struct result<This(Tag, Modifiers)>
  66. {
  67. typedef typename remove_const<
  68. typename remove_reference<Tag>::type>::type
  69. tag_type;
  70. typedef typename remove_const<
  71. typename remove_reference<Modifiers>::type>::type
  72. modifiers_type;
  73. typedef typename mpl::if_<
  74. is_modifier_directive<Domain, tag_type>
  75. , compound_modifier<modifiers_type, tag_type>
  76. , Modifiers>::type
  77. type;
  78. };
  79. template <typename Tag, typename Modifiers>
  80. typename result<modify(Tag, Modifiers)>::type
  81. operator()(Tag tag, Modifiers modifiers) const
  82. {
  83. return op(tag, modifiers, is_modifier_directive<Domain, Tag>());
  84. }
  85. template <typename Tag, typename Modifiers>
  86. Modifiers
  87. op(Tag /*tag*/, Modifiers modifiers, mpl::false_) const
  88. {
  89. return modifiers;
  90. }
  91. template <typename Tag, typename Modifiers>
  92. compound_modifier<Modifiers, Tag>
  93. op(Tag tag, Modifiers modifiers, mpl::true_) const
  94. {
  95. return compound_modifier<Modifiers, Tag>(modifiers, tag);
  96. }
  97. };
  98. }}
  99. namespace boost { namespace proto
  100. {
  101. template <typename Domain, typename Enable>
  102. struct is_callable<spirit::modify<Domain, Enable> >
  103. : mpl::true_ {};
  104. }}
  105. #endif