liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*=============================================================================
    Copyright (c) 2020 Nikita Kniazev
 
    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef BOOST_SPIRIT_X3_SUPPORT_TRAITS_ATTRIBUTE_OF_BINARY
#define BOOST_SPIRIT_X3_SUPPORT_TRAITS_ATTRIBUTE_OF_BINARY
 
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
#include <boost/spirit/home/x3/support/unused.hpp>
#include <boost/type_traits/type_identity.hpp>
 
namespace boost { namespace spirit { namespace x3 { namespace detail
{
    template <typename... T>
    struct type_sequence
    {
        using type = type_sequence;
 
        static const int size = sizeof...(T);
 
        template <typename... U>
        using append = type_sequence<T..., U...>;
 
        template <typename... U>
        using prepend = type_sequence<U..., T...>;
 
        template <typename U>
        using extend = typename U::template prepend<T...>;
 
        template <template <typename...> class U>
        using transfer_to = U<T...>;
    };
 
    template <typename Attribute>
    struct types_of_binary_init : type_sequence<Attribute> {};
    template <>
    struct types_of_binary_init<unused_type> : type_sequence<> {};
    template <>
    struct types_of_binary_init<unused_type const> : type_sequence<> {};
 
    template <template <typename, typename> class B, typename P, typename C>
    struct get_types_of_binary
      : types_of_binary_init<typename traits::attribute_of<P, C>::type> {};
    template <template <typename, typename> class B, typename L, typename R, typename C>
    struct get_types_of_binary<B, B<L, R>, C>
      : get_types_of_binary<B, L, C>::template extend<get_types_of_binary<B, R, C>> {};
 
    template <template <typename...> class A, typename T, int = T::size>
    struct type_sequence_to_attribute { using type = typename T::template transfer_to<A>; };
    template <template <typename...> class A, typename T>
    struct type_sequence_to_attribute<A, T, 1> : T::template transfer_to<type_identity> {};
    template <template <typename...> class A, typename T>
    struct type_sequence_to_attribute<A, T, 0> { using type = unused_type; };
 
    template <template <typename...> class A, template <typename, typename> class B,
        typename L, typename R, typename C>
    using attribute_of_binary = type_sequence_to_attribute<A,
                                    typename get_types_of_binary<B, B<L, R>, C>::type>;
}}}}
#endif