Non riesco a inizializzare gli elementi std::tuple
element-wise da un std::tuple
di tipi compatibili. Perché non funziona come con boost::tuple
?Perché non posso std :: tuple essere costruito in base agli elementi con una tupla di tipi :: std :: compatibili?
#include <tuple>
#include <boost/tuple/tuple.hpp>
template <typename T>
struct Foo
{
// error: cannot convert 'std::tuple<int>' to 'int' in initialization
template <typename U>
Foo(U &&u) : val(std::forward<U>(u)) {}
T val;
};
int main()
{
boost::tuple<Foo<int>>{boost::tuple<int>{}}; // ok
auto a = boost::tuple<int>{};
boost::tuple<Foo<int>>{a}; // ok
std::tuple<Foo<int>>{std::tuple<int>{}}; // fails with rvalue
auto b = std::tuple<int>{};
std::tuple<Foo<int>>{b}; // fails with lvalue
}
Live on Coliru (GCC o Clang e libstdC++ non compila, tuttavia Clang e libC++ compila senza errori)
std::tuple
non sta facendo elemento-saggio costruzione e istanzia Foo<int>::Foo<std::tuple<int>>
anziché Foo<int>::Foo<int>
. Ho pensato std::tuple::tuple
overloads no. 4 and 5 erano esattamente a tale scopo:
template <class... UTypes>
tuple(const tuple<UTypes...>& other);
template <class... UTypes>
tuple(tuple<UTypes...>&& other);
Nota:
non partecipa nella risoluzione di sovraccarico a meno
std::is_constructible<Ti, const Ui&>::value
ètrue
per tuttii
.
std::is_constructible<Foo<int>, int>::value
è true
. Dall'errore del modello GCC, posso vedere che il sovraccarico no. 3:
template <class... UTypes>
explicit tuple(UTypes&&... args);
è selezionato. Perché?
Ok, non funziona con '-std = libstdC++', ma funziona con '-std = libC++' su Clang. Deve essere un problema di implementazione. – LogicStuff
Segnala un bug nel bugzilla di gcc. –
Questa domanda fornirà comunque informazioni preziose per coloro che incontreranno lo stesso problema. Dirà loro che il problema è con l'implementazione della libreria standard e non nel loro codice. Ci sono molti obiettivi comuni di dupe che sono la spiegazione del particolare bug di implementazione (MinGW e 'stoi' per esempio) –