summaryrefslogtreecommitdiff
path: root/boost/phoenix/stl/container/detail/container.hpp
blob: fb6cad2fe90a84dd38afec107855f45995c9ce7c (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
169
170
171
172
173
/*=============================================================================
    Copyright (c) 2004 Angus Leeming
    Copyright (c) 2004 Joel de Guzman

    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_PHOENIX_CONTAINER_DETAIL_CONTAINER_HPP
#define BOOST_PHOENIX_CONTAINER_DETAIL_CONTAINER_HPP

#include <utility>
#include <boost/mpl/eval_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_const.hpp>

namespace boost { namespace phoenix { namespace stl
{
///////////////////////////////////////////////////////////////////////////////
//
//  Metafunctions "value_type_of", "key_type_of" etc.
//
//      These metafunctions define a typedef "type" that returns the nested
//      type if it exists. If not then the typedef returns void.
//
//      For example, "value_type_of<std::vector<int> >::type" is "int" whilst
//      "value_type_of<double>::type" is "void".
//
//      I use a macro to define structs "value_type_of" etc simply to cut
//      down on the amount of code. The macro is #undef-ed immediately after
//      its final use.
//
/////////////////////////////////////////////////////////////////c//////////////
#define MEMBER_TYPE_OF(MEMBER_TYPE)                                             \
    template <typename C>                                                       \
    struct BOOST_PP_CAT(MEMBER_TYPE, _of)                                       \
    {                                                                           \
        typedef typename C::MEMBER_TYPE type;                                   \
    }

    MEMBER_TYPE_OF(allocator_type);
    MEMBER_TYPE_OF(const_iterator);
    MEMBER_TYPE_OF(const_reference);
    MEMBER_TYPE_OF(const_reverse_iterator);
    MEMBER_TYPE_OF(container_type);
    MEMBER_TYPE_OF(data_type);
    MEMBER_TYPE_OF(iterator);
    MEMBER_TYPE_OF(key_compare);
    MEMBER_TYPE_OF(key_type);
    MEMBER_TYPE_OF(reference);
    MEMBER_TYPE_OF(reverse_iterator);
    MEMBER_TYPE_OF(size_type);
    MEMBER_TYPE_OF(value_compare);
    MEMBER_TYPE_OF(value_type);

#undef MEMBER_TYPE_OF

///////////////////////////////////////////////////////////////////////////////
//
//  Const-Qualified types.
//
//      Many of the stl member functions have const and non-const
//      overloaded versions that return distinct types. For example:
//
//          iterator begin();
//          const_iterator begin() const;
//
//      The three class templates defined below,
//      const_qualified_reference_of, const_qualified_iterator_of
//      and const_qualified_reverse_iterator_of provide a means to extract
//      this return type automatically.
//
///////////////////////////////////////////////////////////////////////////////
    template <typename C>
    struct const_qualified_reference_of
    {
        typedef typename
            boost::mpl::eval_if_c<
                boost::is_const<C>::value
              , const_reference_of<C>
              , reference_of<C>
            >::type
        type;
    };

    template <typename C>
    struct const_qualified_iterator_of
    {
        typedef typename
            boost::mpl::eval_if_c<
                boost::is_const<C>::value
              , const_iterator_of<C>
              , iterator_of<C>
            >::type
        type;
    };

    template <typename C>
    struct const_qualified_reverse_iterator_of
    {
        typedef typename
            boost::mpl::eval_if_c<
                boost::is_const<C>::value
              , const_reverse_iterator_of<C>
              , reverse_iterator_of<C>
            >::type
        type;
    };

///////////////////////////////////////////////////////////////////////////////
//
//  has_mapped_type<C>
//
//      Given a container C, determine if it is a map or multimap
//      by checking if it has a member type named "mapped_type".
//
///////////////////////////////////////////////////////////////////////////////
    namespace stl_impl
    {
        struct one { char a[1]; };
        struct two { char a[2]; };

        template <typename C>
        one has_mapped_type(typename C::mapped_type(*)());

        template <typename C>
        two has_mapped_type(...);
    }

    template <typename C>
    struct has_mapped_type
        : boost::mpl::bool_<
            sizeof(stl_impl::has_mapped_type<C>(0)) == sizeof(stl_impl::one)
        >
    {};

///////////////////////////////////////////////////////////////////////////////
//
//  map_insert_returns_pair<C>
//
//      Distinguish a map from a multimap by checking the return type
//      of its "insert" member function. A map returns a pair while
//      a multimap returns an iterator.
//
///////////////////////////////////////////////////////////////////////////////
    namespace stl_impl
    {
        //  Cool implementation of map_insert_returns_pair by Daniel Wallin.
        //  Thanks Daniel!!! I owe you a Pizza!

        template<class A, class B>
        one map_insert_returns_pair_check(std::pair<A,B> const&);

        template <typename T>
        two map_insert_returns_pair_check(T const&);

        template <typename C>
        struct map_insert_returns_pair
        {
            static typename C::value_type const& get;
            BOOST_STATIC_CONSTANT(int,
                value = sizeof(
                    map_insert_returns_pair_check(((C*)0)->insert(get))));
            typedef boost::mpl::bool_<value == sizeof(one)> type;
        };
    }

    template <typename C>
    struct map_insert_returns_pair
        : stl_impl::map_insert_returns_pair<C>::type {};

}}} // namespace boost::phoenix::stl

#endif // BOOST_PHOENIX_STL_CONTAINER_TRAITS_HPP