Skip to content

Commit 1b7eca8

Browse files
committed
[tuple] Few tests and assign implementation
1 parent 28c1876 commit 1b7eca8

File tree

5 files changed

+537
-61
lines changed

5 files changed

+537
-61
lines changed

include/rsl/tuple

Lines changed: 142 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <rsl/_impl/index_of.hpp>
99
#include <rsl/_impl/member_cache.hpp>
1010
#include <rsl/util/to_string.hpp>
11+
#include <rsl/utility>
1112

1213
#ifndef RSL_STD_COMPAT
1314
# define RSL_STD_COMPAT 1
@@ -91,23 +92,23 @@ concept is_implicitly_default_constructible = std::is_default_constructible_v<T>
9192
#ifdef __clang__
9293
template <typename T, std::size_t Idx>
9394
struct SubscriptElement {
94-
constexpr decltype(auto) operator[](std::size_t idx) &
95-
__attribute__((enable_if(idx == Idx, "index mismatch"))) {
95+
constexpr decltype(auto) operator[](
96+
std::size_t idx) & __attribute__((enable_if(idx == Idx, "index mismatch"))) {
9697
return get<Idx>(static_cast<T&>(*this));
9798
}
9899

99-
constexpr decltype(auto) operator[](std::size_t idx) const&
100-
__attribute__((enable_if(idx == Idx, "index mismatch"))) {
100+
constexpr decltype(auto) operator[](
101+
std::size_t idx) const& __attribute__((enable_if(idx == Idx, "index mismatch"))) {
101102
return get<Idx>(static_cast<T const&>(*this));
102103
}
103104

104-
constexpr decltype(auto) operator[](std::size_t idx) &&
105-
__attribute__((enable_if(idx == Idx, "index mismatch"))) {
105+
constexpr decltype(auto) operator[](
106+
std::size_t idx) && __attribute__((enable_if(idx == Idx, "index mismatch"))) {
106107
return get<Idx>(static_cast<T&&>(*this));
107108
}
108109

109-
constexpr decltype(auto) operator[](std::size_t idx) const&&
110-
__attribute__((enable_if(idx == Idx, "index mismatch"))) {
110+
constexpr decltype(auto) operator[](
111+
std::size_t idx) const&& __attribute__((enable_if(idx == Idx, "index mismatch"))) {
111112
return get<Idx>(static_cast<T const&&>(*this));
112113
}
113114
};
@@ -127,7 +128,6 @@ struct Subscript<T, std::index_sequence<Idx...>> : SubscriptElement<T, Idx>... {
127128
#endif
128129
} // namespace _tuple_impl
129130

130-
131131
namespace _impl {
132132

133133
template <typename... Ts>
@@ -147,18 +147,18 @@ class tuple
147147
#endif
148148
{
149149
private:
150+
template <typename... Us>
151+
constexpr static bool enable_utypes_ctor =
152+
!std::same_as<tuple, Us...[0]> && (std::is_constructible_v<Types, Us> && ...);
150153

151-
template <typename... Us>
152-
constexpr static bool enable_utypes_ctor = !std::same_as<tuple, Us...[0]> && (std::is_constructible_v<Types, Us> && ...);
153-
154-
template<>
155-
constexpr bool enable_utypes_ctor<> = false;
154+
template <>
155+
constexpr bool enable_utypes_ctor<> = false;
156156

157-
template <typename... Us>
158-
constexpr static bool enable_utypes_tuple_ctor = true; // TODO
157+
template <typename... Us>
158+
constexpr static bool enable_utypes_tuple_ctor = true; // TODO
159159

160-
template <>
161-
constexpr bool enable_utypes_tuple_ctor<> = false;
160+
template <>
161+
constexpr bool enable_utypes_tuple_ctor<> = false;
162162

163163
public:
164164
template <typename... Ts>
@@ -172,10 +172,13 @@ public:
172172

173173
// template <typename... UTypes>
174174
// static constexpr auto _impl_disambiguation_constraint =
175-
// (sizeof...(Types) == 1 && !std::same_as<std::remove_cvref_t<rsl::tuple_element_t<0, rsl::tuple<UTypes...>>>, tuple>) ||
175+
// (sizeof...(Types) == 1 && !std::same_as<std::remove_cvref_t<rsl::tuple_element_t<0,
176+
// rsl::tuple<UTypes...>>>, tuple>) ||
176177
// ((sizeof...(Types) == 2 || sizeof...(Types) == 3) &&
177-
// (!std::same_as<std::remove_cvref_t<rsl::tuple_element_t<0, rsl::tuple<UTypes...>>>, std::allocator_arg_t> ||
178-
// std::same_as<std::remove_cvref_t<rsl::tuple_element_t<0, rsl::tuple<Types...>>>, std::allocator_arg_t>)) ||
178+
// (!std::same_as<std::remove_cvref_t<rsl::tuple_element_t<0, rsl::tuple<UTypes...>>>,
179+
// std::allocator_arg_t> ||
180+
// std::same_as<std::remove_cvref_t<rsl::tuple_element_t<0, rsl::tuple<Types...>>>,
181+
// std::allocator_arg_t>)) ||
179182
// sizeof...(Types) >= 1;
180183

181184
// [tuple.cnstr], tuple construction
@@ -211,32 +214,32 @@ public:
211214
requires(std::is_move_constructible_v<Storage>)
212215
= default;
213216

214-
template <class... UTypes>
215-
constexpr explicit(!(std::is_convertible_v<UTypes&, Types> && ...))
216-
tuple(tuple<UTypes...>& other)
217-
noexcept((std::is_nothrow_constructible_v<Types, UTypes&> && ...))
218-
requires(false) // TODO
219-
: _impl_storage(other) {}
220-
221-
template <class... UTypes>
222-
constexpr explicit(!(std::is_convertible_v<UTypes const&, Types> && ...))
223-
tuple(tuple<UTypes...> const& other)
224-
noexcept((std::is_nothrow_constructible_v<Types, UTypes const&> && ...))
225-
requires(false) // TODO
226-
: _impl_storage(other) {}
227-
228-
template <class... UTypes>
229-
constexpr explicit(!(std::is_convertible_v<UTypes, Types> && ...))
230-
tuple(tuple<UTypes...>&& other)
231-
noexcept((std::is_nothrow_constructible_v<Types, UTypes> && ...))
232-
requires(false) // TODO
233-
: _impl_storage(std::move(other)) {}
234-
235-
template <class... UTypes>
236-
constexpr explicit(!(std::is_convertible_v<UTypes, Types> && ...))
237-
tuple(tuple<UTypes...> const&& other)
238-
requires(false) // TODO
239-
: _impl_storage(std::move(other)) {}
217+
template <class... UTypes>
218+
constexpr explicit(!(std::is_convertible_v<UTypes&, Types> && ...))
219+
tuple(tuple<UTypes...>& other) noexcept((std::is_nothrow_constructible_v<Types, UTypes&> &&
220+
...))
221+
requires(false) // TODO
222+
: _impl_storage(other) {}
223+
224+
template <class... UTypes>
225+
constexpr explicit(!(std::is_convertible_v<UTypes const&, Types> && ...))
226+
tuple(tuple<UTypes...> const& other) noexcept(
227+
(std::is_nothrow_constructible_v<Types, UTypes const&> && ...))
228+
requires(false) // TODO
229+
: _impl_storage(other) {}
230+
231+
template <class... UTypes>
232+
constexpr explicit(!(std::is_convertible_v<UTypes, Types> && ...))
233+
tuple(tuple<UTypes...>&& other) noexcept((std::is_nothrow_constructible_v<Types, UTypes> &&
234+
...))
235+
requires(false) // TODO
236+
: _impl_storage(std::move(other)) {}
237+
238+
template <class... UTypes>
239+
constexpr explicit(!(std::is_convertible_v<UTypes, Types> && ...))
240+
tuple(tuple<UTypes...> const&& other)
241+
requires(false) // TODO
242+
: _impl_storage(std::move(other)) {}
240243

241244
// template <class U1, class U2>
242245
// constexpr explicit(true /* TODO*/) tuple(std::pair<U1, U2>&); // only if
@@ -300,19 +303,98 @@ public:
300303
}
301304

302305
// [tuple.assign], tuple assignment
303-
// constexpr tuple& operator=(const tuple&);
304-
// constexpr const tuple& operator=(const tuple&) const;
305-
// constexpr tuple& operator=(tuple&&) noexcept(true /* TODO */);
306-
// constexpr const tuple& operator=(tuple&&) const;
307-
308-
// template <class... UTypes>
309-
// constexpr tuple& operator=(const tuple<UTypes...>&);
310-
// template <class... UTypes>
311-
// constexpr const tuple& operator=(const tuple<UTypes...>&) const;
312-
// template <class... UTypes>
313-
// constexpr tuple& operator=(tuple<UTypes...>&&);
314-
// template <class... UTypes>
315-
// constexpr const tuple& operator=(tuple<UTypes...>&&) const;
306+
307+
constexpr tuple& operator=(const tuple& other)
308+
requires(std::ranges::all_of(_impl_accessor.types, std::meta::is_copy_assignable_type))
309+
{
310+
template for (constexpr auto el : define_static_array(
311+
nonstatic_data_members_of(^^Storage, std::meta::access_context::current()))) {
312+
this->_impl_storage.[:el:] = other._impl_storage.[:el:];
313+
}
314+
return *this;
315+
}
316+
317+
constexpr const tuple& operator=(const tuple& other) const
318+
noexcept(std::ranges::all_of(_impl_accessor.types,
319+
std::meta::is_nothrow_copy_constructible_type))
320+
requires(std::ranges::all_of(_impl_accessor.types,
321+
[](std::meta::info type) consteval {
322+
return std::meta::is_copy_assignable_type(
323+
std::meta::add_const(type));
324+
}))
325+
{
326+
template for (constexpr auto el : define_static_array(
327+
nonstatic_data_members_of(^^Storage, std::meta::access_context::current()))) {
328+
this->_impl_storage.[:el:] = other._impl_storage.[:el:];
329+
}
330+
return *this;
331+
}
332+
333+
constexpr tuple& operator=(tuple&& other) noexcept(
334+
std::ranges::all_of(_impl_accessor.types, std::meta::is_nothrow_move_constructible_type))
335+
requires(std::ranges::all_of(_impl_accessor.types,
336+
std::meta::is_move_assignable_type)) // tuple.assign-8
337+
{
338+
this->_impl_storage = std::move(other._impl_storage);
339+
return *this;
340+
}
341+
342+
constexpr const tuple& operator=(tuple&& other) const
343+
requires(std::ranges::all_of(_impl_accessor.types, // tuple.assign-12
344+
[](std::meta::info type) consteval {
345+
return std::meta::is_assignable_type(std::meta::add_const(type),
346+
type);
347+
}))
348+
{
349+
template for (constexpr auto el : define_static_array(
350+
nonstatic_data_members_of(^^Storage, std::meta::access_context::current()))) {
351+
this->_impl_storage.[:el:] = std::move(other._impl_storage.[:el:]);
352+
}
353+
return *this;
354+
}
355+
356+
template <class... UTypes>
357+
requires(sizeof...(UTypes) == sizeof...(Types) &&
358+
(std::is_assignable_v<Types&, UTypes const&> && ...)) // tuple-assign-15
359+
constexpr tuple& operator=(const tuple<UTypes...>& other) {
360+
template for (constexpr auto Idx : rsl::make_index_sequence<sizeof...(Types)>()) {
361+
this->get<Idx>() = other.template get<Idx>();
362+
}
363+
return *this;
364+
}
365+
template <class... UTypes>
366+
requires(sizeof...(UTypes) == sizeof...(Types) &&
367+
(std::is_assignable_v<const Types&, const UTypes&> && ...)) // tuple-assign-18
368+
constexpr const tuple& operator=(const tuple<UTypes...>& other) const {
369+
template for (constexpr auto Idx : rsl::make_index_sequence<sizeof...(Types)>()) {
370+
constexpr auto el = define_static_array(
371+
nonstatic_data_members_of(^^Storage, std::meta::access_context::current()))[Idx];
372+
this->_impl_storage.[:el:] = other.template get<Idx>();
373+
}
374+
return *this;
375+
}
376+
377+
template <class... UTypes>
378+
requires(sizeof...(UTypes) == sizeof...(Types) &&
379+
(std::is_assignable_v<Types&, UTypes> && ...)) // tuple-assign-21
380+
constexpr tuple& operator=(tuple<UTypes...>&& other) {
381+
template for (constexpr auto Idx : rsl::make_index_sequence<sizeof...(Types)>()) {
382+
this->get<Idx>() = std::forward<UTypes...[Idx]>(other.template get<Idx>());
383+
}
384+
return *this;
385+
}
386+
387+
template <class... UTypes>
388+
requires(sizeof...(UTypes) == sizeof...(Types) &&
389+
(std::is_assignable_v<const Types&, UTypes> && ...)) // tuple-assign-24
390+
constexpr const tuple& operator=(tuple<UTypes...>&& other) const {
391+
template for (constexpr auto Idx : rsl::make_index_sequence<sizeof...(Types)>()) {
392+
constexpr auto el = define_static_array(
393+
nonstatic_data_members_of(^^Storage, std::meta::access_context::current()))[Idx];
394+
this->_impl_storage.[:el:] = std::forward<UTypes...[Idx]>(other.template get<Idx>());
395+
}
396+
return *this;
397+
}
316398

317399
// template <class U1, class U2>
318400
// constexpr tuple& operator=(const std::pair<U1, U2>&); // only if sizeof...(Types) == 2

test/tuple/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
target_sources(rsl-util-test PRIVATE
22
structured_bindings.cpp
33
empty.cpp
4+
assign.cpp
5+
tie.cpp
6+
make_tuple.cpp
47
)
58

69
add_subdirectory(tuple.get)
7-
add_subdirectory(extensions)
10+
add_subdirectory(extensions)

0 commit comments

Comments
 (0)