2009-12-09 87 views
0

我试图将一些代码从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; 
} 

难道仅仅是确切的语法不支持,那一个微小的变化将使其工作,或者我需要更改代码以避免这样的专业化?如果后者是一般这样做的最佳方式?

回答

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; 

如果省略前声明,编译器没有办法知道是否实例化函数或使用明确的特化。前向声明告诉它。

+0

+1的答案,也见矿为标准的摘录。 – 2009-12-09 17:39:20

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:

An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member. An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member.