我正在尝试将一些代码从VC9移植到G ++,但是我遇到了模板特化的问题,显然不允许类成员使用。
以下代码是类方法的getValue特化的这些错误的示例。在所有情况下,错误都是“错误:非命名空间范围class ...
中的显式特化”
template<typename T> T getValue(const_iterator key)const
{
try{return boost::lexical_cast<T>(key->second);}
catch(boost::bad_lexical_cast &e)
{
throw TypeParseError<T>(name, key->first, e.what());
}
}
template<typename T> T getValue(const std::string &key)const
{
iterator i = find(key);
if(i == end())throw KeyNotFound(name,key);
else return getValue(i);
}
template<> std::string getValue<std::string>(const_iterator key)const
{
return key->second;
}
template<> std::string getValue<std::string>(const std::string &key)const
{
const_iterator i = find(key);
if(i == end())throw KeyNotFound(name,key);
else return i->second;
}
是否只是不支持确切的语法,并且稍微更改会使其工作,还是我需要更改代码以避免像这样的特殊化?如果后者这是一般的最佳方式吗?
答案 0 :(得分:7)
您没有显示包含这些函数声明的类定义。但是我假设它是一些声明这些模板的类。你必须在外面定义特化:
struct SomeClass {
template<typename T> T getValue(const_iterator key)const
{
try{return boost::lexical_cast<T>(key->second);}
catch(boost::bad_lexical_cast &e)
{
throw TypeParseError<T>(name, key->first, e.what());
}
}
template<typename T> T getValue(const std::string &key)const
{
iterator i = find(key);
if(i == end())throw KeyNotFound(name,key);
else return getValue(i);
}
};
template<> inline std::string SomeClass::getValue<std::string>(const_iterator key)const {
return key->second;
}
template<> inline std::string SomeClass::getValue<std::string>(const std::string &key)const {
const_iterator i = find(key);
if(i == end())throw KeyNotFound(name,key);
else return i->second;
}
请记住,由于您已在外部定义它们,因此它们不是隐式内联的,因此您必须明确地内联它们,或者将它们移动到cpp
文件(而不是标题)中,并向前声明标题中的特化如下:
template<> inline std::string SomeClass::getValue<std::string>(const_iterator key)const;
template<> inline std::string SomeClass::getValue<std::string>(const std::string &key)const;
如果省略forward-declaration,编译器无法知道是实例化函数还是使用显式特化。前方声明告诉它。
答案 1 :(得分:3)
MSVC允许在类范围内进行显式特化,而标准则不允许。
从我所看到的,你给出的代码来自一个类定义。专注于课堂范围之外。
template<> inline std::string Foo::getValue<std::string>(const_iterator key)const {
return key->second;
}
template<> inline std::string Foo::getValue<std::string>(const std::string &key)const {
const_iterator i = find(key);
if(i == end())throw KeyNotFound(name,key);
else return i->second;
}
请参阅:
14.7.3.2:
应在名称空间中声明显式特化 哪个模板是成员,或者,对于成员模板,在 封闭类或封闭类模板所在的命名空间 成员。成员函数的明确特化,成员 类模板的类或静态数据成员应声明 类模板所属的命名空间。