File indexing completed on 2025-01-31 10:02:38
0001
0002
0003
0004
0005
0006
0007
0008 #if !defined(BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM)
0009 #define BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM
0010
0011 #include <boost/spirit/home/x3/support/traits/container_traits.hpp>
0012 #include <boost/fusion/include/is_sequence.hpp>
0013 #include <boost/fusion/include/map.hpp>
0014 #include <boost/fusion/include/value_at_key.hpp>
0015 #include <boost/fusion/adapted/mpl.hpp>
0016 #include <boost/mpl/placeholders.hpp>
0017 #include <boost/mpl/equal.hpp>
0018 #include <boost/mpl/apply.hpp>
0019 #include <boost/mpl/filter_view.hpp>
0020 #include <boost/mpl/size.hpp>
0021 #include <boost/mpl/logical.hpp>
0022 #include <boost/mpl/at.hpp>
0023 #include <boost/mpl/count_if.hpp>
0024 #include <boost/utility/enable_if.hpp>
0025 #include <boost/optional/optional.hpp>
0026 #include <boost/type_traits/is_same.hpp>
0027
0028 namespace boost { namespace spirit { namespace x3 { namespace traits
0029 {
0030
0031
0032
0033 template <typename T, typename Attribute, typename Enable = void>
0034 struct is_substitute;
0035
0036 template <typename Variant, typename Attribute>
0037 struct variant_has_substitute;
0038
0039 namespace detail
0040 {
0041 template <typename T, typename Attribute>
0042 struct value_type_is_substitute
0043 : is_substitute<
0044 typename container_value<T>::type
0045 , typename container_value<Attribute>::type>
0046 {};
0047
0048 template <typename T, typename Attribute, typename Enable = void>
0049 struct is_substitute_impl : mpl::false_ {};
0050
0051 template <typename T, typename Attribute>
0052 struct is_substitute_impl<T, Attribute,
0053 typename enable_if<
0054 mpl::and_<
0055 fusion::traits::is_sequence<T>,
0056 fusion::traits::is_sequence<Attribute>,
0057 mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>>
0058 >
0059 >::type>
0060 : mpl::true_ {};
0061
0062 template <typename T, typename Attribute>
0063 struct is_substitute_impl<T, Attribute,
0064 typename enable_if<
0065 mpl::and_<
0066 is_container<T>,
0067 is_container<Attribute>,
0068 value_type_is_substitute<T, Attribute>
0069 >
0070 >::type>
0071 : mpl::true_ {};
0072
0073 template <typename T, typename Attribute>
0074 struct is_substitute_impl<T, Attribute,
0075 typename enable_if<
0076 is_variant<Attribute>
0077 >::type>
0078 : variant_has_substitute<Attribute, T>
0079 {};
0080 }
0081
0082 template <typename T, typename Attribute, typename Enable >
0083 struct is_substitute
0084 : mpl::or_<
0085 is_same<T, Attribute>,
0086 detail::is_substitute_impl<T, Attribute>> {};
0087
0088
0089 template <typename T, typename Attribute, typename Enable>
0090 struct is_substitute<T&, Attribute, Enable>
0091 : is_substitute<T, Attribute, Enable> {};
0092
0093
0094 template <typename T, typename Attribute, typename Enable>
0095 struct is_substitute<T, Attribute&, Enable>
0096 : is_substitute<T, Attribute, Enable> {};
0097
0098
0099
0100
0101 template <typename T, typename Attribute>
0102 struct is_substitute<T, Attribute
0103 , typename enable_if<
0104 typename mpl::eval_if<
0105 mpl::and_<fusion::traits::is_sequence<T>
0106 , fusion::traits::is_sequence<Attribute>>
0107 , mpl::and_<traits::has_size<T, 2>
0108 , fusion::traits::is_associative<Attribute>>
0109 , mpl::false_>::type>::type>
0110
0111 {
0112
0113
0114 typedef typename mpl::at_c<T, 0>::type p_key;
0115 typedef typename mpl::at_c<T, 1>::type p_value;
0116
0117
0118
0119
0120 template <typename Key, typename Value, typename Map>
0121 struct has_kv_in_map
0122 : mpl::eval_if<
0123 fusion::result_of::has_key<Map, Key>
0124 , mpl::apply<
0125 is_substitute<
0126 fusion::result_of::value_at_key<mpl::_1, Key>
0127 , Value>
0128 , Map>
0129 , mpl::false_>
0130 {};
0131
0132
0133
0134
0135
0136 template <typename Variant>
0137 struct variant_kv
0138 : mpl::equal_to<
0139 mpl::size< typename Variant::types>
0140 , mpl::size< mpl::filter_view<typename Variant::types
0141 , has_kv_in_map<mpl::_1, p_value, Attribute>>>
0142 >
0143 {};
0144
0145 typedef typename
0146 mpl::eval_if<
0147 is_variant<p_key>
0148 , variant_kv<p_key>
0149 , has_kv_in_map<p_key, p_value, Attribute>
0150 >::type
0151 type;
0152 };
0153
0154 template <typename T, typename Attribute>
0155 struct is_substitute<optional<T>, optional<Attribute>>
0156 : is_substitute<T, Attribute> {};
0157 }}}}
0158
0159 #endif