My full code is too long, but here is a snippet that will reflect the essence of my 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 {
}
};
}
When I compile this code, I get the following errors:
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>’
Now I have to specialize std::hash for these classes (because standard std::hash definition does not include user defined types). When I move these template specializations before the definition of class BPCFGParser
, I get a variety of errors for a variety of different things tried, and somewhere (http://www.parashift.com/c++-faq-lite/misc-technical-issues.html) I read that:
Whenever you use a class as a template parameter, the declaration of that class must be complete and not simply forward declared.
So I'm stuck. I cannot specialize the templates after BPCFGParser
definition, I cannot specialize them before BPCFGParser
definition, how may I get this working?
You need to move the specialization into an inner class inside of BPCFGParser. Doing so meets both requirements.
Thank you very much for the answer :)
hash
class is defined within the namespace std
. It does not allow me to specialize the templates for hash
in a non-namespace scope. Even the following:
template <>
class std::hash<ActiveEquivClass> {
...
did not work. When I enclose the specializations with namespace std {}
, however, it gives the weird error of:
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 an answer given in velocityreviews, someone claims that namespaces cannot be defined within classes. So I'm still stuck.
You need to move the specialization into an inner class inside of BPCFGParser. Doing so meets both requirements
ActiveEquivClass
Example:
class BPCFGParser {
class ActiveEquivClass {
...
};
template <>
class hash<ActiveEquivClass> {
public:
size_t operator()(const BPCFGParser::ActiveEquivClass & aec) const {
}
};
...
unordered_map<ActiveEquivClass, Edge *, hash<ActiveEquivClass>, EqActiveEquivClass> discovered_active_edges;
};