summaryrefslogtreecommitdiff
path: root/boost/unordered/detail/extract_key.hpp
blob: 338e918ca9a3a46c56cf347e1ff74addb83f6a7f (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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

// Copyright (C) 2005-2011 Daniel James
// 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_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED

#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif

#include <boost/unordered/detail/table.hpp>

namespace boost {
namespace unordered {
namespace detail {

    // key extractors
    //
    // no throw
    //
    // 'extract_key' is called with the emplace parameters to return a
    // key if available or 'no_key' is one isn't and will need to be
    // constructed. This could be done by overloading the emplace implementation
    // for the different cases, but that's a bit tricky on compilers without
    // variadic templates.

    struct no_key {
        no_key() {}
        template <class T> no_key(T const&) {}
    };

    template <typename Key, typename T>
    struct is_key {
        template <typename T2>
        static choice1::type test(T2 const&);
        static choice2::type test(Key const&);
        
        enum { value = sizeof(test(boost::unordered::detail::make<T>())) ==
            sizeof(choice2::type) };
        
        typedef typename boost::detail::if_true<value>::
            BOOST_NESTED_TEMPLATE then<Key const&, no_key>::type type;
    };

    template <class ValueType>
    struct set_extractor
    {
        typedef ValueType value_type;
        typedef ValueType key_type;

        static key_type const& extract(value_type const& v)
        {
            return v;
        }

        static no_key extract()
        {
            return no_key();
        }
        
        template <class Arg>
        static no_key extract(Arg const&)
        {
            return no_key();
        }

#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
        template <class Arg1, class Arg2, class... Args>
        static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
        {
            return no_key();
        }
#else
        template <class Arg1, class Arg2>
        static no_key extract(Arg1 const&, Arg2 const&)
        {
            return no_key();
        }
#endif
    };

    template <class Key, class ValueType>
    struct map_extractor
    {
        typedef ValueType value_type;
        typedef typename boost::remove_const<Key>::type key_type;

        static key_type const& extract(value_type const& v)
        {
            return v.first;
        }
            
        template <class Second>
        static key_type const& extract(std::pair<key_type, Second> const& v)
        {
            return v.first;
        }

        template <class Second>
        static key_type const& extract(
            std::pair<key_type const, Second> const& v)
        {
            return v.first;
        }

        template <class Arg1>
        static key_type const& extract(key_type const& k, Arg1 const&)
        {
            return k;
        }

        static no_key extract()
        {
            return no_key();
        }

        template <class Arg>
        static no_key extract(Arg const&)
        {
            return no_key();
        }

        template <class Arg1, class Arg2>
        static no_key extract(Arg1 const&, Arg2 const&)
        {
            return no_key();
        }

#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
        template <class Arg1, class Arg2, class Arg3, class... Args>
        static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
                Args const&...)
        {
            return no_key();
        }
#endif

#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)

#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_)                          \
        template <typename T2>                                              \
        static no_key extract(boost::unordered::piecewise_construct_t,      \
                namespace_ tuple<> const&, T2 const&)                       \
        {                                                                   \
            return no_key();                                                \
        }                                                                   \
                                                                            \
        template <typename T, typename T2>                                  \
        static typename is_key<key_type, T>::type                           \
            extract(boost::unordered::piecewise_construct_t,                \
                namespace_ tuple<T> const& k, T2 const&)                    \
        {                                                                   \
            return typename is_key<key_type, T>::type(                      \
                namespace_ get<0>(k));                                      \
        }

#else

#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_)                          \
        static no_key extract(boost::unordered::piecewise_construct_t,      \
                namespace_ tuple<> const&)                                  \
        {                                                                   \
            return no_key();                                                \
        }                                                                   \
                                                                            \
        template <typename T>                                               \
        static typename is_key<key_type, T>::type                           \
            extract(boost::unordered::piecewise_construct_t,                \
                namespace_ tuple<T> const& k)                               \
        {                                                                   \
            return typename is_key<key_type, T>::type(                      \
                namespace_ get<0>(k));                                      \
        }

#endif

BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
#endif
    };
}}}

#endif