1 year ago
#388512

Red.Wave
Why is there still no move-from-elements ctor for `std::tuple'?
Long while ago I faced a question very much like this one:
std::tuple default constructor with move-constructable element
C++ is evolving and improving at a high rate, but minor changes to code still bite a programmers toes. I tested adding a SFINAE opted ctor for exact match move-from-elements ctor and just put the problem away.
Now a flashback took me to the problem again.
std::tuple
just declares 26 (=13*2) constructors. I wonder why it is still lacking one for exact match move from elements? The pair <2,15> define exact match copy from elements. This pair defeats the pair<3,16> overloads (generic make from universal reference list). A move from counterpart does not seem that difficult. SFINAE has become a lot simpler with concepts finally shipping:
template<typename ... Types>
tuple<Types ...>::tuple(Types&&... args)
requires(!(is_lvalue_reference_v<Types>&&...&&true));
template<typename Alloc, typename ... Types>
tuple<Types ...>::tuple( std::allocator_arg_t, const Alloc&, Types&&... args)
requires(!(is_lvalue_reference_v<Types>&&...&&true));
The SFINAE just prevents a duplicate definition for copy-from-elements counterparts, in case all elements are rvalue references; otherwise - if at least one value or rvalue reference element exists - a new pair of constructors will be available. Has there been any other specific reason preventing this pair of constructors from being declared?
Here is the snippet that exemplifies the point:
struct A{
A()=default;
A(A&&){endl(std::cout<<"A(A&&)");};
A(A const&){endl(std::cout<<"A(A const&)");};
};
struct B{
B()=default;
B(B&&){endl(std::cout<<"B(B&&)");};
B(B const&){endl(std::cout<<"B(B const&)");};
};
struct C{
C()=default;
C(C&&){endl(std::cout<<"C(C&&)");};
C(C const&){endl(std::cout<<"C(C const&)");};
};
std::tuple<A,B,C> abc={{},{},{}};
The output is the signature of copy ctors of the classes. Because none-templated ctor#2 is prefered over ctor#3. Now if either of the copy ctors of classes is commented out(=delete
d), the code just fails to compile; because ctor#3 is explicit
as it should be. While the proposed new constructors should be only conditionally explicit
(if either element is explicitly moveable).
c++
tuples
std
stdtuple
isocpp
0 Answers
Your Answer