| 1 | /*============================================================================= |
| 2 | Copyright (c) 2020 Nikita Kniazev |
| 3 | |
| 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_X3_SUPPORT_TRAITS_ATTRIBUTE_OF_BINARY |
| 8 | #define BOOST_SPIRIT_X3_SUPPORT_TRAITS_ATTRIBUTE_OF_BINARY |
| 9 | |
| 10 | #include <boost/spirit/home/x3/support/traits/attribute_of.hpp> |
| 11 | #include <boost/spirit/home/x3/support/unused.hpp> |
| 12 | #include <boost/type_traits/type_identity.hpp> |
| 13 | |
| 14 | namespace boost { namespace spirit { namespace x3 { namespace detail |
| 15 | { |
| 16 | template <typename... T> |
| 17 | struct type_sequence |
| 18 | { |
| 19 | using type = type_sequence; |
| 20 | |
| 21 | static const int size = sizeof...(T); |
| 22 | |
| 23 | template <typename... U> |
| 24 | using append = type_sequence<T..., U...>; |
| 25 | |
| 26 | template <typename... U> |
| 27 | using prepend = type_sequence<U..., T...>; |
| 28 | |
| 29 | template <typename U> |
| 30 | using extend = typename U::template prepend<T...>; |
| 31 | |
| 32 | template <template <typename...> class U> |
| 33 | using transfer_to = U<T...>; |
| 34 | }; |
| 35 | |
| 36 | template <typename Attribute> |
| 37 | struct types_of_binary_init : type_sequence<Attribute> {}; |
| 38 | template <> |
| 39 | struct types_of_binary_init<unused_type> : type_sequence<> {}; |
| 40 | template <> |
| 41 | struct types_of_binary_init<unused_type const> : type_sequence<> {}; |
| 42 | |
| 43 | template <template <typename, typename> class B, typename P, typename C> |
| 44 | struct get_types_of_binary |
| 45 | : types_of_binary_init<typename traits::attribute_of<P, C>::type> {}; |
| 46 | template <template <typename, typename> class B, typename L, typename R, typename C> |
| 47 | struct get_types_of_binary<B, B<L, R>, C> |
| 48 | : get_types_of_binary<B, L, C>::template extend<get_types_of_binary<B, R, C>> {}; |
| 49 | |
| 50 | template <template <typename...> class A, typename T, int = T::size> |
| 51 | struct type_sequence_to_attribute { using type = typename T::template transfer_to<A>; }; |
| 52 | template <template <typename...> class A, typename T> |
| 53 | struct type_sequence_to_attribute<A, T, 1> : T::template transfer_to<type_identity> {}; |
| 54 | template <template <typename...> class A, typename T> |
| 55 | struct type_sequence_to_attribute<A, T, 0> { using type = unused_type; }; |
| 56 | |
| 57 | template <template <typename...> class A, template <typename, typename> class B, |
| 58 | typename L, typename R, typename C> |
| 59 | using attribute_of_binary = type_sequence_to_attribute<A, |
| 60 | typename get_types_of_binary<B, B<L, R>, C>::type>; |
| 61 | }}}} |
| 62 | #endif |
| 63 | |