]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/x3/support/traits/is_substitute.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / x3 / support / traits / is_substitute.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2014 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 #if !defined(BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM)
9 #define BOOST_SPIRIT_X3_IS_SUBSTITUTE_JAN_9_2012_1049PM
10
11 #include <boost/spirit/home/x3/support/traits/container_traits.hpp>
12 #include <boost/fusion/include/is_sequence.hpp>
13 #include <boost/fusion/include/map.hpp>
14 #include <boost/fusion/include/value_at_key.hpp>
15 #include <boost/fusion/adapted/mpl.hpp>
16 #include <boost/mpl/placeholders.hpp>
17 #include <boost/mpl/equal.hpp>
18 #include <boost/mpl/apply.hpp>
19 #include <boost/mpl/filter_view.hpp>
20 #include <boost/mpl/size.hpp>
21 #include <boost/mpl/logical.hpp>
22 #include <boost/mpl/at.hpp>
23 #include <boost/mpl/count_if.hpp>
24 #include <boost/utility/enable_if.hpp>
25 #include <boost/optional/optional.hpp>
26 #include <boost/type_traits/is_same.hpp>
27
28 namespace boost { namespace spirit { namespace x3 { namespace traits
29 {
30 ///////////////////////////////////////////////////////////////////////////
31 // Find out if T can be a (strong) substitute for Attribute
32 ///////////////////////////////////////////////////////////////////////////
33 template <typename T, typename Attribute, typename Enable = void>
34 struct is_substitute;
35
36 template <typename Variant, typename Attribute>
37 struct variant_has_substitute;
38
39 namespace detail
40 {
41 template <typename T, typename Attribute>
42 struct value_type_is_substitute
43 : is_substitute<
44 typename container_value<T>::type
45 , typename container_value<Attribute>::type>
46 {};
47
48 template <typename T, typename Attribute, typename Enable = void>
49 struct is_substitute_impl : is_same<T, Attribute> {};
50
51 template <typename T, typename Attribute>
52 struct is_substitute_impl<T, Attribute,
53 typename enable_if<
54 mpl::and_<
55 fusion::traits::is_sequence<T>,
56 fusion::traits::is_sequence<Attribute>,
57 mpl::equal<T, Attribute, is_substitute<mpl::_1, mpl::_2>>
58 >
59 >::type>
60 : mpl::true_ {};
61
62 template <typename T, typename Attribute>
63 struct is_substitute_impl<T, Attribute,
64 typename enable_if<
65 mpl::and_<
66 is_container<T>,
67 is_container<Attribute>,
68 value_type_is_substitute<T, Attribute>
69 >
70 >::type>
71 : mpl::true_ {};
72
73 template <typename T, typename Attribute>
74 struct is_substitute_impl<T, Attribute,
75 typename enable_if<
76 is_variant<Attribute>
77 >::type>
78 : mpl::or_<
79 is_same<T, Attribute>
80 , variant_has_substitute<Attribute, T>
81 >
82 {};
83 }
84
85 template <typename T, typename Attribute, typename Enable /*= void*/>
86 struct is_substitute
87 : detail::is_substitute_impl<T, Attribute> {};
88
89 // for reference T
90 template <typename T, typename Attribute, typename Enable>
91 struct is_substitute<T&, Attribute, Enable>
92 : is_substitute<T, Attribute, Enable> {};
93
94 // for reference Attribute
95 template <typename T, typename Attribute, typename Enable>
96 struct is_substitute<T, Attribute&, Enable>
97 : is_substitute<T, Attribute, Enable> {};
98
99 // 2 element mpl tuple is compatible with fusion::map if:
100 // - it's first element type is existing key in map
101 // - it second element type is compatible to type stored at the key in map
102 template <typename T, typename Attribute>
103 struct is_substitute<T, Attribute
104 , typename enable_if<
105 typename mpl::eval_if<
106 mpl::and_<fusion::traits::is_sequence<T>
107 , fusion::traits::is_sequence<Attribute>>
108 , mpl::and_<traits::has_size<T, 2>
109 , fusion::traits::is_associative<Attribute>>
110 , mpl::false_>::type>::type>
111
112 {
113 // checking that "p_key >> p_value" parser can
114 // store it's result in fusion::map attribute
115 typedef typename mpl::at_c<T, 0>::type p_key;
116 typedef typename mpl::at_c<T, 1>::type p_value;
117
118 // for simple p_key type we just check that
119 // such key can be found in attr and that value under that key
120 // matches p_value
121 template <typename Key, typename Value, typename Map>
122 struct has_kv_in_map
123 : mpl::eval_if<
124 fusion::result_of::has_key<Map, Key>
125 , mpl::apply<
126 is_substitute<
127 fusion::result_of::value_at_key<mpl::_1, Key>
128 , Value>
129 , Map>
130 , mpl::false_>
131 {};
132
133 // if p_key is variant over multiple types (as a result of
134 // "(key1|key2|key3) >> p_value" parser) check that all
135 // keys are found in fusion::map attribute and that values
136 // under these keys match p_value
137 template <typename Variant>
138 struct variant_kv
139 : mpl::equal_to<
140 mpl::size< typename Variant::types>
141 , mpl::size< mpl::filter_view<typename Variant::types
142 , has_kv_in_map<mpl::_1, p_value, Attribute>>>
143 >
144 {};
145
146 typedef typename
147 mpl::eval_if<
148 is_variant<p_key>
149 , variant_kv<p_key>
150 , has_kv_in_map<p_key, p_value, Attribute>
151 >::type
152 type;
153 };
154
155 template <typename T, typename Attribute>
156 struct is_substitute<optional<T>, optional<Attribute>>
157 : is_substitute<T, Attribute> {};
158 }}}}
159
160 #endif