Spezialisierung der Vorlage nach der Instanzierung?
Mein vollständiger code ist zu lang, aber hier ist ein snippet, dass spiegeln die Essenz der mein problem:
class BPCFGParser {
public:
...
...
class Edge {
...
...
};
class ActiveEquivClass {
...
...
};
class PassiveEquivClass {
...
...
};
struct EqActiveEquivClass {
...
...
};
struct EqPassiveEquivClass {
...
...
};
unordered_map<ActiveEquivClass, Edge *, hash<ActiveEquivClass>, EqActiveEquivClass> discovered_active_edges;
unordered_map<PassiveEquivClass, Edge *, hash<PassiveEquivClass>, EqPassiveEquivClass> discovered_passive_edges;
};
namespace std {
template <>
class hash<BPCFGParser::ActiveEquivClass>
{
public:
size_t operator()(const BPCFGParser::ActiveEquivClass & aec) const {
}
};
template <>
class hash<BPCFGParser::PassiveEquivClass>
{
public:
size_t operator()(const BPCFGParser::PassiveEquivClass & pec) const {
}
};
}
Wenn ich diesen code kompilieren möchte, bekomme ich folgenden Fehler:
In file included from BPCFGParser.cpp:3,
from experiments.cpp:2:
BPCFGParser.h:408: error: specialization of ‘std::hash<BPCFGParser::ActiveEquivClass>’ after instantiation
BPCFGParser.h:408: error: redefinition of ‘class std::hash<BPCFGParser::ActiveEquivClass>’
/usr/include/c++/4.3/tr1_impl/functional_hash.h:44: error: previous definition of ‘class std::hash<BPCFGParser::ActiveEquivClass>’
BPCFGParser.h:445: error: specialization of ‘std::hash<BPCFGParser::PassiveEquivClass>’ after instantiation
BPCFGParser.h:445: error: redefinition of ‘class std::hash<BPCFGParser::PassiveEquivClass>’
/usr/include/c++/4.3/tr1_impl/functional_hash.h:44: error: previous definition of ‘class std::hash<BPCFGParser::PassiveEquivClass>’
Nun habe ich zu spezialisieren, std::hash für diese Klassen (weil standard std::hash definition nicht enthalten benutzerdefinierte Typen). Wenn ich mich bewege, die template-Spezialisierungen vor der definition der Klasse BPCFGParser
, bekomme ich eine Vielzahl von Fehlern für eine Vielzahl von verschiedenen Dingen versucht, und irgendwo (http://www.parashift.com/c++-faq-lite/misc-technical-issues.html) ich habe gelesen, dass:
, Wenn Sie eine Klasse als template-parameter, die Deklaration der Klasse muss vollständig sein und nicht einfach nach vorne erklärt.
So, ich bin stecken. Ich kann mich nicht spezialisieren sich die Vorlagen nach BPCFGParser
definition ist, kann ich nicht spezialisieren, Sie vor BPCFGParser
definition, wie bekomme ich diese zu arbeiten?
Müssen Sie bewegen die Spezialisierung in eine innere Klasse innerhalb der BPCFGParser. Dabei erfüllt beide Anforderungen.
Vielen Dank für die Antwort 🙂
hash
Klasse ist definiert im namespace std
. Es nicht erlauben, mich zu spezialisieren, die Vorlagen für hash
in einem nicht-namespace-Gültigkeitsbereich. Auch die folgenden:
template <>
class std::hash<ActiveEquivClass> {
...
nicht funktioniert. Wenn ich schließen Sie den Spezialisierungen mit namespace std {}
aber es gibt die seltsame Fehlermeldung von:
In file included from BPCFGParser.cpp:3,
from experiments.cpp:2:
BPCFGParser.h:225: error: expected unqualified-id before ‘namespace’
experiments.cpp:7: error: expected `}' at end of input
BPCFGParser.h:222: error: expected unqualified-id at end of input
In einer Antwort in velocityreviews, jemand behauptet, dass namespaces können nicht definiert werden, innerhalb von Klassen. Also ich bin immer noch stecken.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie bewegen die Spezialisierung in eine innere Klasse innerhalb der BPCFGParser. Dabei erfüllt beide Anforderungen
ActiveEquivClass
Beispiel:
Versuchen Sie, den hash<> template-Spezialisierung-code vor dem BPCFGParser Klasse Erklärung. Der Fehler bedeutet, dass hash erweitert, basierend auf std::hash definiert /usr/include/c++/4.3/tr1_impl/functional_hash.h, So dass Ihre Spezialisierung nicht verwendet wird, bevor die Instanziierung. Im Idealfall, Ihre Spezialisierung-code verfügbar gemacht werden sollten, für den compiler, bevor Sie die Vorlage erweitert.
Dies ist nicht wirklich wahr. Die Einschränkungen bei der template-Parameter müssen vollständig sein Typen ist in der Regel abhängig von der Vorlage Inhalt; aber es ist nicht illegal zu instanziieren der Schablone mit einem unvollständigen Typ, solange die Vorlage nicht enthalten code, dass ist illegal mit einem unvollständigen Typ.
Der einzige Weg, Ihr problem zu definieren, die Spezialisierung vor der Klasse, sondern definieren die eigentliche Memberfunktion
operator()
nach der Klasse. Das ist,Dies bedeutet auch, keine verschachtelten Klassen, als Sie nicht vorwärts deklarieren Sie eine geschachtelte Klasse.
Ich habe genau das gleiche problem und endlich eine Problemumgehung Benutzer-definierte hash-Funktor Lösung, siehe unten:
Und ich bin noch Fragen, ob es eine std::hash Spezialisierung Ansatz. Kann das jemand herausfinden?
Ich weiß, diese Frage ist schon ziemlich alt, aber ich habe gerade über das gleiche problem, und ich dachte, ich würde meine Erkenntnisse.
Die Fehlermeldung:
beklagt sich nicht über Ihre Klassen überhaupt, es ist, dass Sie nicht spezialisiert std::hash, da entweder die generische Vorlage für std::hash oder eine der vorhandenen Spezialisierungen bereits verwendet wurde, d.h. jemand hat es genutzt, zwischen dem Punkt, an dem Sie definiert wurde, und dem Punkt, wo Sie versucht sind, sich zu spezialisieren, es.
Text beschreibt dies in der "im detail" - Abschnitt dieses Dokument:
In meinem Fall nicht das problem mit meiner Spezialisierung-code, das problem war mit seiner position. Einmal std::hash verwendet wurde, können Sie sich nicht spezialisieren sich weiter.
Ich festgestellt, dass wenn ich zog meine Spezialisierung-code sofort nach inklusive <unordered_map>, es funktionierte.
Dem Vorschlag von Welpen zu trennen, die Erklärung der Spezialisierung von der Umsetzung können Sie verschieben die Erklärungen sehr nah an die Einbeziehung von <unordered_map> die Umsetzung kann später kommen, wo es bequem ist (nach BPCFGParser voll definiert in Ihrem Fall).