1 year ago

#388512

test-img

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(=deleted), 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

Accepted video resources