Skip to content

Commit c2727f9

Browse files
authored
Merge pull request #30 from rsl-org/tuple/converting_constructor
Add missing implementation for converting constructor and tests
2 parents 9fa7b5f + c04abe5 commit c2727f9

5 files changed

Lines changed: 982 additions & 39 deletions

File tree

include/rsl/tuple

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ private:
172172
}
173173
}
174174

175+
template <typename T, size_t... Is>
176+
constexpr storage_type _impl_converting_constructor(T&& o, std::index_sequence<Is...>) {
177+
return {([&]()->Types... [Is] {
178+
if constexpr (std::is_reference_v<Types...[Is]>)
179+
return o.template get<Is>();
180+
else
181+
return Types... [Is] { std::forward_like<T>(o.template get<Is>()) };
182+
}())...};
183+
}
184+
175185
public:
176186
storage_type _impl_storage;
177187
static constexpr auto _impl_accessor = [:_impl::cache_members(nonstatic_data_members_of(
@@ -190,64 +200,95 @@ public:
190200
// sizeof...(Types) >= 1;
191201

192202
// [tuple.cnstr], tuple construction
193-
constexpr explicit((!_tuple_impl::is_implicitly_default_constructible<Types> || ...))
203+
constexpr explicit((!_tuple_impl::is_implicitly_default_constructible<Types> ||
204+
...)) // [tuple.cnstr]/8
194205
tuple() noexcept(std::is_nothrow_default_constructible_v<storage_type>)
195-
requires(std::is_default_constructible_v<storage_type>)
206+
requires(sizeof...(Types) >= 1 &&
207+
std::is_default_constructible_v<storage_type>) // [tuple.cnstr]/6
196208
= default;
197209

198-
constexpr explicit(!(std::is_convertible_v<Types const&, Types> && ...))
210+
constexpr tuple() noexcept
211+
requires(sizeof...(Types) == 0)
212+
= default; // [tuple.cnstr]/5
213+
214+
constexpr explicit(!(std::is_convertible_v<Types const&, Types> && ...)) // [tuple.cnstr]/11
199215
tuple(Types const&... values) noexcept((std::is_nothrow_copy_constructible_v<Types> && ...))
200-
requires(sizeof...(Types) >= 1 && (std::is_copy_constructible_v<Types> && ...))
216+
requires(sizeof...(Types) >= 1 &&
217+
(std::is_copy_constructible_v<Types> && ...)) // [tuple.cnstr]/9
201218
: _impl_storage{values...} {}
202219

203220
template <class... UTypes>
204-
requires(sizeof...(UTypes) == sizeof...(Types) &&
205-
!(std::reference_constructs_from_temporary_v<Types, UTypes &&> ||
206-
...) && // TODO required?
221+
requires(sizeof...(UTypes) == sizeof...(Types) && // [tuple.cnstr]/13.1
222+
sizeof...(UTypes) >= 1 && // [tuple.cnstr]/13.2
207223
enable_utypes_ctor<UTypes...> &&
208-
(std::is_constructible_v<Types, UTypes> && ...))
209-
constexpr explicit(!(std::is_convertible_v<UTypes, Types> && ...)) tuple(UTypes&&... values)
224+
(std::is_constructible_v<Types, UTypes> && ...)) // [tuple.cnstr]/13.3
225+
constexpr explicit(!(std::is_convertible_v<UTypes, Types> && ...)) // [tuple.cnstr]/15
226+
tuple(UTypes&&... values)
210227
: _impl_storage(std::forward<UTypes>(values)...) {}
211228

212229
template <class... UTypes>
213230
requires(sizeof...(UTypes) == sizeof...(Types) &&
214-
(std::reference_constructs_from_temporary_v<Types, UTypes &&> || ...))
231+
(std::reference_constructs_from_temporary_v<Types, UTypes &&> || // [tuple.cnstr]/15
232+
...))
215233
constexpr tuple(UTypes&&... values) = delete;
216234

217-
tuple(tuple const&) noexcept(std::is_nothrow_copy_constructible_v<storage_type>)
218-
requires(std::is_copy_constructible_v<storage_type>)
235+
constexpr tuple(tuple const&) noexcept(std::is_nothrow_copy_constructible_v<storage_type>)
236+
requires(std::is_copy_constructible_v<storage_type>) // [tuple.cnstr]/16
219237
= default;
220238

221-
tuple(tuple&&) noexcept(std::is_nothrow_move_constructible_v<storage_type>)
222-
requires(std::is_move_constructible_v<storage_type>)
239+
constexpr tuple(tuple&&) noexcept(std::is_nothrow_move_constructible_v<storage_type>)
240+
requires(std::is_move_constructible_v<storage_type>) // [tuple.cnstr]/18
223241
= default;
224242

225243
template <class... UTypes>
226-
constexpr explicit(!(std::is_convertible_v<UTypes&, Types> && ...))
244+
requires(sizeof...(UTypes) == sizeof...(Types)) && // [tuple.cnstr]/21.1
245+
(std::is_constructible_v<Types, UTypes&> && ...) && // [tuple.cnstr]/21.2
246+
(sizeof...(UTypes) != 1 || // [tuple.cnstr]/21.3
247+
(!std::is_convertible_v<tuple<UTypes...>, Types...[0]> && // [tuple.cnstr]/21.3
248+
!std::is_constructible_v<Types...[0], tuple<UTypes...>> && // [tuple.cnstr]/21.3
249+
!std::same_as<Types...[0], UTypes...[0]>)) // [tuple.cnstr]/21.3
250+
constexpr explicit(!(std::is_convertible_v<UTypes&, Types> && ...)) // [tuple.cnstr]/23
227251
tuple(tuple<UTypes...>& other) noexcept((std::is_nothrow_constructible_v<Types, UTypes&> &&
228252
...))
229-
requires(false) // TODO
230-
: _impl_storage(other) {}
253+
: _impl_storage(_impl_converting_constructor(other, std::index_sequence_for<Types...>{})) {}
231254

232255
template <class... UTypes>
233-
constexpr explicit(!(std::is_convertible_v<UTypes const&, Types> && ...))
256+
requires(sizeof...(UTypes) == sizeof...(Types)) && // [tuple.cnstr]/21.1
257+
(std::is_constructible_v<Types, UTypes&> && ...) && // [tuple.cnstr]/21.2
258+
(sizeof...(UTypes) != 1 || // [tuple.cnstr]/21.3
259+
(!std::is_convertible_v<tuple<UTypes...>, Types...[0]> && // [tuple.cnstr]/21.3
260+
!std::is_constructible_v<Types...[0], tuple<UTypes...>> && // [tuple.cnstr]/21.3
261+
!std::same_as<Types...[0], UTypes...[0]>)) // [tuple.cnstr]/21.3
262+
constexpr explicit(!(std::is_convertible_v<UTypes&, Types> && ...)) // [tuple.cnstr]/23
234263
tuple(tuple<UTypes...> const& other) noexcept(
235-
(std::is_nothrow_constructible_v<Types, UTypes const&> && ...))
236-
requires(false) // TODO
237-
: _impl_storage(other) {}
264+
(std::is_nothrow_constructible_v<Types, UTypes&> && ...))
265+
: _impl_storage(_impl_converting_constructor(other, std::index_sequence_for<Types...>{})) {}
238266

239267
template <class... UTypes>
240-
constexpr explicit(!(std::is_convertible_v<UTypes, Types> && ...))
241-
tuple(tuple<UTypes...>&& other) noexcept((std::is_nothrow_constructible_v<Types, UTypes> &&
268+
requires(sizeof...(UTypes) == sizeof...(Types)) && // [tuple.cnstr]/21.1
269+
(std::is_constructible_v<Types, UTypes &&> && ...) && // [tuple.cnstr]/21.2
270+
(sizeof...(UTypes) != 1 || // [tuple.cnstr]/21.3
271+
(!std::is_convertible_v<tuple<UTypes...>, Types...[0]> && // [tuple.cnstr]/21.3
272+
!std::is_constructible_v<Types...[0], tuple<UTypes...>> && // [tuple.cnstr]/21.3
273+
!std::same_as<Types...[0], UTypes...[0]>)) // [tuple.cnstr]/21.3
274+
constexpr explicit(!(std::is_convertible_v<UTypes&&, Types> && ...)) // [tuple.cnstr]/23
275+
tuple(tuple<UTypes...>&& other) noexcept((std::is_nothrow_constructible_v<Types, UTypes&> &&
242276
...))
243-
requires(false) // TODO
244-
: _impl_storage(std::move(other)) {}
277+
: _impl_storage(
278+
_impl_converting_constructor(std::move(other), std::index_sequence_for<Types...>{})) {}
245279

246280
template <class... UTypes>
247-
constexpr explicit(!(std::is_convertible_v<UTypes, Types> && ...))
248-
tuple(tuple<UTypes...> const&& other)
249-
requires(false) // TODO
250-
: _impl_storage(std::move(other)) {}
281+
requires(sizeof...(UTypes) == sizeof...(Types)) && // [tuple.cnstr]/21.1
282+
(std::is_constructible_v<Types, UTypes &&> && ...) && // [tuple.cnstr]/21.2
283+
(sizeof...(UTypes) != 1 || // [tuple.cnstr]/21.3
284+
(!std::is_convertible_v<tuple<UTypes...>, Types...[0]> && // [tuple.cnstr]/21.3
285+
!std::is_constructible_v<Types...[0], tuple<UTypes...>> && // [tuple.cnstr]/21.3
286+
!std::same_as<Types...[0], UTypes...[0]>)) // [tuple.cnstr]/21.3
287+
constexpr explicit(!(std::is_convertible_v<UTypes&&, Types> && ...)) // [tuple.cnstr]/23
288+
tuple(tuple<UTypes...> const&& other) noexcept(
289+
(std::is_nothrow_constructible_v<Types, UTypes&> && ...))
290+
: _impl_storage(
291+
_impl_converting_constructor(std::move(other), std::index_sequence_for<Types...>{})) {}
251292

252293
// template <class U1, class U2>
253294
// constexpr explicit(true /* TODO*/) tuple(std::pair<U1, U2>&); // only if

0 commit comments

Comments
 (0)