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/type_traits/is_base_of.hpp> 16 #include <boost/spirit/home/support/unused.hpp> 17 18 namespace boost { namespace spirit 19 { 20 template <typename Domain, typename T, typename Enable = void> 21 struct is_modifier_directive; 22 23 // Testing if a modifier set includes a modifier T involves 24 // checking for inheritance (i.e. Modifiers is derived from T) 25 template <typename Modifiers, typename T> 26 struct has_modifier 27 : is_base_of<T, Modifiers> {}; 28 29 // Adding modifiers is done using multi-inheritance 30 template <typename Current, typename New, typename Enable = void> 31 struct compound_modifier : Current, New 32 { compound_modifierboost::spirit::compound_modifier33 compound_modifier() 34 : Current(), New() {} 35 compound_modifierboost::spirit::compound_modifier36 compound_modifier(Current const& current, New const& new_) 37 : Current(current), New(new_) {} 38 }; 39 40 // Don't add if New is already in Current 41 template <typename Current, typename New> 42 struct compound_modifier< 43 Current, New, typename enable_if<has_modifier<Current, New> >::type> 44 : Current 45 { compound_modifierboost::spirit::compound_modifier46 compound_modifier() 47 : Current() {} 48 compound_modifierboost::spirit::compound_modifier49 compound_modifier(Current const& current, New const&) 50 : Current(current) {} 51 }; 52 53 // Special case if Current is unused_type 54 template <typename New, typename Enable> 55 struct compound_modifier<unused_type, New, Enable> : New 56 { compound_modifierboost::spirit::compound_modifier57 compound_modifier() 58 : New() {} 59 compound_modifierboost::spirit::compound_modifier60 compound_modifier(unused_type, New const& new_) 61 : New(new_) {} 62 }; 63 64 // Domains may specialize this modify metafunction to allow 65 // directives to add information to the Modifier template 66 // parameter that is passed to the make_component metafunction. 67 // By default, we return the modifiers untouched 68 template <typename Domain, typename Enable = void> 69 struct modify 70 { 71 typedef void proto_is_callable_; 72 73 template <typename Sig> 74 struct result; 75 76 template <typename This, typename Tag, typename Modifiers> 77 struct result<This(Tag, Modifiers)> 78 { 79 typedef typename remove_const< 80 typename remove_reference<Tag>::type>::type 81 tag_type; 82 typedef typename remove_const< 83 typename remove_reference<Modifiers>::type>::type 84 modifiers_type; 85 86 typedef typename mpl::if_< 87 is_modifier_directive<Domain, tag_type> 88 , compound_modifier<modifiers_type, tag_type> 89 , Modifiers>::type 90 type; 91 }; 92 93 template <typename Tag, typename Modifiers> 94 typename result<modify(Tag, Modifiers)>::type operator ()boost::spirit::modify95 operator()(Tag tag, Modifiers modifiers) const 96 { 97 return op(tag, modifiers, is_modifier_directive<Domain, Tag>()); 98 } 99 100 template <typename Tag, typename Modifiers> 101 Modifiers opboost::spirit::modify102 op(Tag /*tag*/, Modifiers modifiers, mpl::false_) const 103 { 104 return modifiers; 105 } 106 107 template <typename Tag, typename Modifiers> 108 compound_modifier<Modifiers, Tag> opboost::spirit::modify109 op(Tag tag, Modifiers modifiers, mpl::true_) const 110 { 111 return compound_modifier<Modifiers, Tag>(modifiers, tag); 112 } 113 }; 114 }} 115 116 #endif 117