【问题标题】:Problem with class template specialisations类模板特化的问题
【发布时间】:2009-12-09 17:00:13
【问题描述】:

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

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

【问题讨论】:

    标签: c++ visual-c++ scope g++ specialization


    【解决方案1】:

    您还没有显示包含这些函数声明的类定义。但我认为这是在其中声明这些模板的某个类。您必须在外部定义专业化:

    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;
    

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

    【讨论】:

    • +1 为答案,另见我的标准摘录。
    【解决方案2】:

    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:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多