Ich implementiere zur Zeit eine Dataset-Helper-Klassenvorlage, die Fließkommawerte (Scalar
) in einer Eigen::Matrix
dynamischen Struktur aus einem Vektor von verschiedene Werttypen (Element
), die zusätzlich einen Verweis auf diesen Eingabevektor speichern. Jetzt möchte ich den Konstruktor im Vektorwerttyp teilweise spezialisieren, der eine Vorlage im Skalartyp bleibt, der explizit instanziiert wird.C++, partielle Spezialisierung der 2-Argumente-Klasse Vorlage: Funktionserkennung kann nicht mit einer vorhandenen Deklaration übereinstimmen
Leider so einfach „nicht in der Lage zu Funktionsdefinition zu einer vorhandenen Deklaration überein:“ Ich bin immer auf VS 2010. Der Code ist als:
template <class Scalar, class Element> struct DataSet
{
DataSet(std::vector<Element> const & source);
// several generic member functions here ...
Eigen::Matrix<Scalar, ... > data;
std::vector<Element> const & source;
};
template<class Scalar>
DataSet<Scalar, SomeClass>::DataSet(std::vector<SomeClass> const & input)
{
// special impl for Element==SomeClass ...
}
Someclass vom Compiler automatisch herausgefunden werden soll, wenn richtig gemacht, aber ich versuchte, alle sinnvollen Kombinationen, aber noch immer:
*.cpp(79) C2244 : unable to match function definition to an existing declaration
see declaration of 'DataSet<Scalar, Element>::DataSet'
ich nicht in der Lage war noch durch die Suche im Internet ein passendes Beispiel zu finden. Danke im Voraus!
EDIT:
Um es präziser zu machen, die ich in meinem realen Welt Fall, dass mehrere Teil Spezialisierungen an den Konstruktor mit verschiedenen Typen für Element
zB definieren können:
template<Scalar>
DataSet<Scalar, FirstClass>::DataSet(std::vector<FirstClass> const & first)
: data()
, source(first)
{
// special impl here ...
}
template<Scalar>
DataSet<Scalar, std::shared_ptr<SecondClass> >::DataSet(std::vector<std::shared_ptr<SecondClass> > const & second)
: data()
, source(second)
{
// special impl here ...
}
Es ist nicht erwünscht, die Klasse vollständig auf einen bestimmten Typennamen zu redefinieren/zu spezialisieren. Dann nützt es wenig, eine Vorlage zu sein. Ich möchte die Lösung so wie sie ist, sonst könnte es andere Strategien für mein Problem geben.
FIN:
Da es sieht aus wie nicht möglich ist, nur spezialisiert den Konstruktor den Typ Element
zwischen Klassenvorlage und Konstruktor zu teilen (was irgendwie zu einer impliziten Spezialisierung der Klasse verwandt ist) i entfernt die Referenz source
aus der Klassenvorlage vollständig und kopiert die benötigten Informationen in einen generischen Container und implementiert die Konstruktoren über Überladungen.
Vielen Dank für Ihre Hilfe, aber dies wird nicht den Verweis auf die Quelldaten direkt möglich machen und erhöht Codezeilen im Gegensatz zu meinem ursprünglichen Wunsch, es so einfach wie möglich zu halten. Ich habe diesen Verweis jetzt auf die Quelldaten entfernt und die Informationen zu einem generischen Container zusammengefasst. Die Konstruktoren können jetzt als Überladungen ohne 'Element' implementiert werden. Aber ich bin immer noch Kuriositäten, wo das Problem liegt, weil im Allgemeinen der Weg begonnen wird, sollte der Weg sein, von einem syntaktischen Gesichtspunkt zu gehen. – daku
@daku Es ist etwas intuitiv anzunehmen, dass spezialisierte Vorlagen Mitglieder von der primären "Basis" erben werden, aber das ist einfach nicht der Fall. Dies ist darauf zurückzuführen, dass Vorlagenargumente bedeuten könnten, dass bestimmte Elemente in bestimmten Spezialisierungen vollständig nicht anwendbar sind, wodurch eine implizite "Vererbung" problematisch wird. Wenn dies der Fall ist, muss entschieden werden, dass eine vollständige Neudeklaration erforderlich ist und es nicht lohnenswert ist, eine Menge arkaner Syntax hinzuzufügen, um anzugeben, ob Mitglieder "geerbt" werden sollen oder nicht, wenn Sie _actual_vererbung einfach verwenden können, um sicherzustellen, dass dies der Fall ist. Aber ich werde sehen, ob ich eine Grundannahme finden kann –
@underscore_d: Das liegt daran, dass Spezialisierung keine Vererbung ist ;-) Die Spezialisierung der Klassenvorlage macht eine komplett neue Klasse. Mein Ziel war es, den Konstruktor zu spezialisieren, was offensichtlich nicht möglich ist, weil 'Element' ein Template-Argument für die Klassenvorlage ist. Es sollte einfach möglich sein, wenn ich den Konstruktor zu einer Template-Funktion mache, aber dann ist es wahrscheinlich nicht möglich, das Argument 'typename Element' zwischen Klassen- und Funktions-Template (für den ctor, oder ist es irgendwie?) Zu teilen. – daku