Line data Source code
1 : //
2 : // Copyright (c) 2016-2019 Damian Jarek (damian dot jarek93 at gmail dot com)
3 : // Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot com)
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/boostorg/beast
9 : //
10 :
11 : #ifndef BOOST_URL_GRAMMAR_DETAIL_TUPLE_HPP
12 : #define BOOST_URL_GRAMMAR_DETAIL_TUPLE_HPP
13 :
14 : #include <boost/url/detail/config.hpp>
15 : #include <boost/url/error_types.hpp>
16 : #include <boost/core/empty_value.hpp>
17 : #include <boost/mp11/algorithm.hpp>
18 : #include <boost/mp11/function.hpp>
19 : #include <boost/mp11/integer_sequence.hpp>
20 : #include <boost/type_traits/remove_cv.hpp>
21 : #include <boost/type_traits/copy_cv.hpp>
22 : #include <cstdlib>
23 : #include <utility>
24 :
25 : #ifndef BOOST_URL_TUPLE_EBO
26 : // VFALCO No idea what causes it or how to fix it
27 : // https://devblogs.microsoft.com/cppblog/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
28 : #ifdef BOOST_MSVC
29 : #define BOOST_URL_TUPLE_EBO 0
30 : #else
31 : #define BOOST_URL_TUPLE_EBO 1
32 : #endif
33 : #endif
34 :
35 : namespace boost {
36 : namespace urls {
37 : namespace grammar {
38 : namespace detail {
39 :
40 : #if BOOST_URL_TUPLE_EBO
41 : template<std::size_t I, class T>
42 : struct tuple_element_impl
43 : : empty_value<T>
44 : {
45 : constexpr
46 29478 : tuple_element_impl(T const& t)
47 : : empty_value<T>(
48 29478 : empty_init, t)
49 : {
50 29478 : }
51 :
52 : constexpr
53 : tuple_element_impl(T&& t)
54 : : empty_value<T>(
55 : empty_init,
56 : std::move(t))
57 : {
58 : }
59 : };
60 : #else
61 : template<std::size_t I, class T>
62 : struct tuple_element_impl
63 : {
64 : T t_;
65 :
66 : constexpr
67 : tuple_element_impl(T const& t)
68 : : t_(t)
69 : {
70 : }
71 :
72 : constexpr
73 : tuple_element_impl(T&& t)
74 : : t_(std::move(t))
75 : {
76 : }
77 :
78 : constexpr
79 : T&
80 : get() noexcept
81 : {
82 : return t_;
83 : }
84 :
85 : constexpr
86 : T const&
87 : get() const noexcept
88 : {
89 : return t_;
90 : }
91 : };
92 : #endif
93 :
94 : template<std::size_t I, class T>
95 : struct tuple_element_impl<I, T&>
96 : {
97 : T& t;
98 :
99 : constexpr
100 : tuple_element_impl(T& t_)
101 : : t(t_)
102 : {
103 : }
104 :
105 : T&
106 : get() const noexcept
107 : {
108 : return t;
109 : }
110 : };
111 :
112 : template<class... Ts>
113 : struct tuple_impl;
114 :
115 : template<class... Ts, std::size_t... Is>
116 : struct tuple_impl<
117 : mp11::index_sequence<Is...>, Ts...>
118 : : tuple_element_impl<Is, Ts>...
119 : {
120 : template<class... Us>
121 : constexpr
122 : explicit
123 10159 : tuple_impl(Us&&... us)
124 : : tuple_element_impl<Is, Ts>(
125 10159 : std::forward<Us>(us))...
126 : {
127 10159 : }
128 : };
129 :
130 : template<class... Ts>
131 : struct tuple
132 : : tuple_impl<
133 : mp11::index_sequence_for<Ts...>, Ts...>
134 : {
135 : template<class... Us,
136 : typename std::enable_if<
137 : mp11::mp_bool<
138 : mp11::mp_all<std::is_constructible<
139 : Ts, Us>...>::value &&
140 : ! mp11::mp_all<std::is_convertible<
141 : Us, Ts>...>::value>::value,
142 : int>::type = 0
143 : >
144 : constexpr
145 : explicit
146 : tuple(Us&&... us) noexcept
147 : : tuple_impl<mp11::index_sequence_for<
148 : Ts...>, Ts...>{std::forward<Us>(us)...}
149 : {
150 : }
151 :
152 : template<class... Us,
153 : typename std::enable_if<
154 : mp11::mp_all<std::is_convertible<
155 : Us, Ts>...>::value,
156 : int>::type = 0
157 : >
158 : constexpr
159 10159 : tuple(Us&&... us) noexcept
160 : : tuple_impl<mp11::index_sequence_for<
161 10159 : Ts...>, Ts...>{std::forward<Us>(us)...}
162 : {
163 10159 : }
164 : };
165 :
166 : //------------------------------------------------
167 :
168 : template<std::size_t I, class T>
169 : constexpr
170 : T&
171 : get(tuple_element_impl<I, T>& te)
172 : {
173 : return te.get();
174 : }
175 :
176 : template<std::size_t I, class T>
177 : constexpr
178 : T const&
179 24685 : get(tuple_element_impl<I, T> const& te)
180 : {
181 24685 : return te.get();
182 : }
183 :
184 : template<std::size_t I, class T>
185 : constexpr
186 : T&&
187 : get(tuple_element_impl<I, T>&& te)
188 : {
189 : return std::move(te.get());
190 : }
191 :
192 : template<std::size_t I, class T>
193 : constexpr
194 : T&
195 : get(tuple_element_impl<I, T&>&& te)
196 : {
197 : return te.get();
198 : }
199 :
200 : template<std::size_t I, class T>
201 : using tuple_element =
202 : typename boost::copy_cv<
203 : mp11::mp_at_c<typename
204 : remove_cv<T>::type,
205 : I>, T>::type;
206 :
207 : } // detail
208 : } // grammar
209 : } // urls
210 : } // boost
211 :
212 : #endif
|