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;
}

是否只是不支持确切的语法,并且稍作更改就会使其工作,还是我需要更改代码以避免这样的专业化?如果是后者,一般来说最好的方法是什么?

4

2 回答 2

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;

如果省略前向声明,编译器将无法知道是实例化函数还是使用显式特化。前向声明告诉它。

于 2009-12-09T17:09:39.600 回答
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:

显式特化应在模板所属的命名空间中声明,或者,对于成员模板,应在封闭类或封闭类模板所属的命名空间中声明。类模板的成员函数、成员类或静态数据成员的显式特化应在类模板所属的命名空间中声明。

于 2009-12-09T17:11:25.797 回答