lundi 23 avril 2018

Constructing tuple of value from tuple of reference, with one-argument templated constructor

I have a tuple of const references std::tuple<const Matrix&, ...> from which I construct a tuple of values std::tuple<Matrix, ...>. For any size of tuple greater than 1, this works fine:

#include <tuple>
#include <Eigen/Core>
using Matrix = Eigen::Matrix3d;

void works() {
    Matrix m1, m2;
    std::tuple<const Matrix &, const Matrix &> tuple_of_ref{m1, m2};

    std::tuple<Matrix, Matrix> t{tuple_of_ref};
}

However, for a tuple of size 1, this code fails to compile:

void fails() {
    Matrix m;
    std::tuple<const Matrix &> tuple_of_ref{m};

    // Tries and fails to instantiate Matrix(std::tuple<const Matrix &>)
    std::tuple<Matrix> t{tuple_of_ref};
}

Note the Matrix class has a templated constructor which accepts std::tuple.

template<typename T>
explicit Matrix(const T& x)

I don't want to use this constructor, and I can't change it since it's third-party code.

I think my works() example properly calls the constructor listed as #4 on cppreference:

template< class... UTypes >
tuple( const tuple<UTypes...>& other );

4) Converting copy-constructor. For all i in sizeof...(UTypes), initializes ith element of the tuple with std::get<i>(other).

The fails() example tries to use this constructor, presumably #3, which I don't want:

template< class... UTypes >
explicit tuple( UTypes&&... args );

3) Converting constructor. Initializes each element of the tuple with the corresponding value in std::forward<Utypes>(args).

How can I make sure tuple's constructor #4 is used for both cases? My real use case is inside a variadic template so I don't know the size of the tuple in advance.

Aucun commentaire:

Enregistrer un commentaire