Sehr geehrte Mitprogrammierer,Std :: Tuple mit generischen Typen wie boost :: any
der folgende Code gibt mir einige Kopfschmerzen. Es versucht ein 'generisches' Objekt (= Objekt, das aus irgendwas konstruiert werden kann) zu einem Tupel hinzuzufügen und dann dieses Tupel zu kopieren.
#include <tuple>
#include <iostream>
#include <typeinfo>
struct anything
{
anything()
{}
anything(const anything&)
{
std::cout << "Called copy c'tor" << std::endl;
}
template<class T>
anything(T arg)
{
std::cout << "Called c'tor with with argument of type " << typeid(arg).name() << std::endl;
// new T(arg); // causes stack overflow
}
};
int main()
{
std::tuple<anything> t;
//
std::cout << "Copy constructing t2, expecting copy c'tor to be called." << std::endl;
std::tuple<anything> t2(t);
return 0;
}
Mit VS 2015 Update 2 es nicht einmal kompilieren, die Linie
std::tuple<anything> t2(t);
löst einen Compiler-Fehler tief in tuple.h. Mit gcc 5.3.1 kompiliert es, aber die Ausgabe ist nicht das, was ich erwarten würde:
Kopieren Sie das Konstruieren t2, erwarte Kopie c'tor aufgerufen werden.
Genannt Kopie c'tor
Genannt c'tor mit mit dem Argument vom Typ St5tupleIJ8anythingEE
Was ich nicht verstehe, ist die letzte Zeile, das heißt, warum der Templat-Konstruktor mit std :: tuple als Argument aufgerufen wird?
Dies ist eigentlich ein Problem der realen Welt. In meiner Anwendung verwende ich ein boost :: Signal der Unterzeichnung
typedef boost::type_erasure::any
<boost::mpl::vector<
boost::type_erasure::typeid_<>,
boost::type_erasure::copy_constructible<>,
boost::type_erasure::less_than_comparable<>,
boost::type_erasure::equality_comparable<>,
boost::type_erasure::relaxed
>> KeyType;
boost::signals2::signal<void(const KeyType&)>
Boost-Signale intern das Argument in einem Tupel wickeln, bevor die Schlitz Funktion mit ihm rief, die schließlich in einem Stapelüberlauf führt, weil das Tupel c'tor ruft den any c'tor mit tuple als Argument an und der any c'tor ruft dann das tuple c'tor mit 'any of tuple' auf und so weiter und weiter und weiter ...
Machen Sie den Template-Konstruktor 'explizit' –
Vielen Dank für die tollen Antworten. Ich habe Barry's akzeptiert, weil es ein bisschen vollständiger ist. –
Dieses Verhalten von Std :: Tupel scheint nicht intuitiv, um es gelinde auszudrücken. Sollte nicht std :: tuple eine Kopierkonstruktorüberladung haben, die einen Verweis auf nicht-const nimmt: tuple (tuple & other) , um sicherzustellen, dass die Zeile std :: tuple t2 (t); macht eine Kopie? –