2009-12-09 91 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.