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