1 
2 // Copyright (C) 2005-2011 Daniel James
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
7 #define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
8 
9 #include <boost/config.hpp>
10 #if defined(BOOST_HAS_PRAGMA_ONCE)
11 #pragma once
12 #endif
13 
14 #include <boost/unordered/detail/table.hpp>
15 
16 namespace boost {
17 namespace unordered {
18 namespace detail {
19 
20     // key extractors
21     //
22     // no throw
23     //
24     // 'extract_key' is called with the emplace parameters to return a
25     // key if available or 'no_key' is one isn't and will need to be
26     // constructed. This could be done by overloading the emplace implementation
27     // for the different cases, but that's a bit tricky on compilers without
28     // variadic templates.
29 
30     struct no_key {
no_keyboost::unordered::detail::no_key31         no_key() {}
no_keyboost::unordered::detail::no_key32         template <class T> no_key(T const&) {}
33     };
34 
35     template <typename Key, typename T>
36     struct is_key {
37         template <typename T2>
38         static choice1::type test(T2 const&);
39         static choice2::type test(Key const&);
40 
41         enum { value = sizeof(test(boost::unordered::detail::make<T>())) ==
42             sizeof(choice2::type) };
43 
44         typedef typename boost::detail::if_true<value>::
45             BOOST_NESTED_TEMPLATE then<Key const&, no_key>::type type;
46     };
47 
48     template <class ValueType>
49     struct set_extractor
50     {
51         typedef ValueType value_type;
52         typedef ValueType key_type;
53 
extractboost::unordered::detail::set_extractor54         static key_type const& extract(key_type const& v)
55         {
56             return v;
57         }
58 
extractboost::unordered::detail::set_extractor59         static no_key extract()
60         {
61             return no_key();
62         }
63 
64         template <class Arg>
extractboost::unordered::detail::set_extractor65         static no_key extract(Arg const&)
66         {
67             return no_key();
68         }
69 
70 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
71         template <class Arg1, class Arg2, class... Args>
extractboost::unordered::detail::set_extractor72         static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
73         {
74             return no_key();
75         }
76 #else
77         template <class Arg1, class Arg2>
extractboost::unordered::detail::set_extractor78         static no_key extract(Arg1 const&, Arg2 const&)
79         {
80             return no_key();
81         }
82 #endif
83     };
84 
85     template <class Key, class ValueType>
86     struct map_extractor
87     {
88         typedef ValueType value_type;
89         typedef typename boost::remove_const<Key>::type key_type;
90 
extractboost::unordered::detail::map_extractor91         static key_type const& extract(value_type const& v)
92         {
93             return v.first;
94         }
95 
96         template <class Second>
extractboost::unordered::detail::map_extractor97         static key_type const& extract(std::pair<key_type, Second> const& v)
98         {
99             return v.first;
100         }
101 
102         template <class Second>
extractboost::unordered::detail::map_extractor103         static key_type const& extract(
104             std::pair<key_type const, Second> const& v)
105         {
106             return v.first;
107         }
108 
109         template <class Arg1>
extractboost::unordered::detail::map_extractor110         static key_type const& extract(key_type const& k, Arg1 const&)
111         {
112             return k;
113         }
114 
extractboost::unordered::detail::map_extractor115         static no_key extract()
116         {
117             return no_key();
118         }
119 
120         template <class Arg>
extractboost::unordered::detail::map_extractor121         static no_key extract(Arg const&)
122         {
123             return no_key();
124         }
125 
126         template <class Arg1, class Arg2>
extractboost::unordered::detail::map_extractor127         static no_key extract(Arg1 const&, Arg2 const&)
128         {
129             return no_key();
130         }
131 
132 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
133         template <class Arg1, class Arg2, class Arg3, class... Args>
extractboost::unordered::detail::map_extractor134         static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
135                 Args const&...)
136         {
137             return no_key();
138         }
139 #endif
140 
141 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
142 
143 #define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_)                          \
144         template <typename T2>                                              \
145         static no_key extract(boost::unordered::piecewise_construct_t,      \
146                 namespace_ tuple<> const&, T2 const&)                       \
147         {                                                                   \
148             return no_key();                                                \
149         }                                                                   \
150                                                                             \
151         template <typename T, typename T2>                                  \
152         static typename is_key<key_type, T>::type                           \
153             extract(boost::unordered::piecewise_construct_t,                \
154                 namespace_ tuple<T> const& k, T2 const&)                    \
155         {                                                                   \
156             return typename is_key<key_type, T>::type(                      \
157                 namespace_ get<0>(k));                                      \
158         }
159 
160 #else
161 
162 #define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_)                          \
163         static no_key extract(boost::unordered::piecewise_construct_t,      \
164                 namespace_ tuple<> const&)                                  \
165         {                                                                   \
166             return no_key();                                                \
167         }                                                                   \
168                                                                             \
169         template <typename T>                                               \
170         static typename is_key<key_type, T>::type                           \
171             extract(boost::unordered::piecewise_construct_t,                \
172                 namespace_ tuple<T> const& k)                               \
173         {                                                                   \
174             return typename is_key<key_type, T>::type(                      \
175                 namespace_ get<0>(k));                                      \
176         }
177 
178 #endif
179 
180 BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
181 
182 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)
183 BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
184 #endif
185     };
186 }}}
187 
188 #endif
189