summaryrefslogtreecommitdiff
path: root/boost/type_erasure/is_subconcept.hpp
blob: c327731094c85ec22ba1866da7235f990d34a055 (plain)
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Boost.TypeErasure library
//
// Copyright 2012 Steven Watanabe
//
// 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)
//
// $Id$

#ifndef BOOST_TYPE_ERASURE_IS_SUBCONCEPT_HPP_INCLUDED
#define BOOST_TYPE_ERASURE_IS_SUBCONCEPT_HPP_INCLUDED

#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/has_key.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_erasure/detail/normalize.hpp>
#include <boost/type_erasure/detail/check_map.hpp>
#include <boost/type_erasure/detail/rebind_placeholders.hpp>
#include <boost/type_erasure/static_binding.hpp>

namespace boost {
namespace type_erasure {
namespace detail {

#ifdef BOOST_TYPE_ERASURE_USE_MP11

template<class S, class K>
struct mp_set_has_key : ::boost::mp11::mp_set_contains<S, K> {};

template<class Super, class Bindings>
struct is_subconcept_f
{
    template<class T>
    using apply = ::boost::mp11::mp_set_contains<Super, ::boost::type_erasure::detail::rebind_placeholders_t<T, Bindings> >;
};

template<class Super>
struct is_subconcept_f<Super, void>
{
    template<class T>
    using apply = ::boost::mp11::mp_set_contains<Super, T>;
};

#endif

template<class Sub, class Super, class PlaceholderMap>
struct is_subconcept_impl {
#ifndef BOOST_TYPE_ERASURE_USE_MP11
    typedef typename ::boost::type_erasure::detail::normalize_concept<
        Super>::concept_set super_set;

    typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
        Super
    >::type placeholder_subs_super;
    
    typedef typename ::boost::type_erasure::detail::normalize_concept<
        Sub>::type normalized_sub;
    typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
        Sub
    >::type placeholder_subs_sub;

    typedef typename ::boost::mpl::eval_if< ::boost::is_same<PlaceholderMap, void>,
        boost::mpl::identity<void>,
        ::boost::type_erasure::detail::convert_deductions<
            PlaceholderMap,
            placeholder_subs_sub,
            placeholder_subs_super
        >
    >::type bindings;

    typedef typename ::boost::mpl::if_< ::boost::is_same<PlaceholderMap, void>,
        ::boost::mpl::_1,
        ::boost::type_erasure::detail::rebind_placeholders<
            ::boost::mpl::_1,
            bindings
        >
    >::type transform;

    typedef typename ::boost::is_same<
        typename ::boost::mpl::find_if<normalized_sub,
            ::boost::mpl::not_<
                ::boost::mpl::has_key<
                    super_set,
                    transform
                >
            >
        >::type,
        typename ::boost::mpl::end<normalized_sub>::type
    >::type type;
#else
    typedef ::boost::type_erasure::detail::normalize_concept_t<Super> super_set;

    typedef ::boost::type_erasure::detail::get_placeholder_normalization_map_t<
        Super
    > placeholder_subs_super;
    
    typedef ::boost::type_erasure::detail::normalize_concept_t<Sub> normalized_sub;
    typedef ::boost::type_erasure::detail::get_placeholder_normalization_map_t<
        Sub
    > placeholder_subs_sub;
    typedef ::boost::mp11::mp_eval_if_c< ::boost::is_same<PlaceholderMap, void>::value,
        void,
        ::boost::type_erasure::detail::convert_deductions_t,
        PlaceholderMap,
        placeholder_subs_sub,
        placeholder_subs_super
    > bindings;

    typedef typename ::boost::mp11::mp_all_of<
        normalized_sub,
        ::boost::type_erasure::detail::is_subconcept_f<super_set, bindings>::template apply
    > type;
#endif
};

}

/**
 * @ref is_subconcept is a boolean metafunction that determines whether
 * one concept is a sub-concept of another.
 *
 * \code
 * is_subconcept<incrementable<>, incrementable<> >             -> true
 * is_subconcept<incrementable<>, addable<> >                   -> false
 * is_subconcept<incrementable<_a>, forward_iterator<_iter>,
 *   mpl::map<mpl::pair<_a, _iter> > >                          -> true
 * \endcode
 *
 * \tparam Sub The sub concept
 * \tparam Super The super concept
 * \tparam PlaceholderMap (optional) An MPL map with keys for
 *   every non-deduced placeholder in Sub.  The
 *   associated value of each key is the corresponding placeholder
 *   in Super.  If @c PlaceholderMap is omitted, @c Super and @c Sub
 *   are presumed to use the same set of placeholders.
 */
template<class Sub, class Super, class PlaceholderMap = void>
struct is_subconcept :
    ::boost::mpl::and_<
        ::boost::type_erasure::detail::check_map<Sub, PlaceholderMap>,
        ::boost::type_erasure::detail::is_subconcept_impl<Sub, Super, PlaceholderMap>
    >::type
{};

#ifndef BOOST_TYPE_ERASURE_DOXYGEN
template<class Sub, class Super>
struct is_subconcept<Sub, Super, void> :
    ::boost::type_erasure::detail::is_subconcept_impl<Sub, Super, void>::type
{};
template<class Sub, class Super, class PlaceholderMap>
struct is_subconcept<Sub, Super, static_binding<PlaceholderMap> > :
    ::boost::mpl::and_<
        ::boost::type_erasure::detail::check_map<Sub, PlaceholderMap>,
        ::boost::type_erasure::detail::is_subconcept_impl<Sub, Super, PlaceholderMap>
    >::type
{};
#endif

}
}

#endif