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__
9293template <typename T, std::size_t Idx>
9394struct 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-
131131namespace _impl {
132132
133133template <typename... Ts>
@@ -147,18 +147,18 @@ class tuple
147147#endif
148148{
149149private:
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
163163public:
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
0 commit comments