模板专门化在链接时失败

Template specialization fails on linking

本文关键字:失败 链接 专门化      更新时间:2023-10-16

我有一个模板专门化的问题,我想了解。我正在使用Visual c++ 10.0(2010)。我有一个这样的类:

class VariableManager
{
public:
    template<typename VarT>
        VarT get(std::string const& name) const
        {
                    // Some code...
        }
   // This method supposed to be fully evaluated, linkable method.   
    template<>
        std::string get<std::string>(std::string const& name) const;
private:
    std::map<std::string, boost::any> mVariables;
};

理论上,因为我专门化了"get"方法,链接器应该能够从目标文件中拾取。相反,如果将该方法放在源文件中,则会得到链接器未解析的引用错误:

    template<>
    std::string VariableManager::get<std::string>(std::string const& name) const
            {
                 // Doing something...
            }

如果我将这个方法作为内联方式放在头文件中,构建就会很顺利。我明白模板的作用是这样的:

        template<typename VarT>
            VarT get(std::string const& name) const;

应该放在头文件中,因为编译器不能根据调用代码对模板进行专门化,但在完全专门化的情况下,是类的实现实现了这一点,因此专门化的模板方法应该已经作为公共符号存在。有人能解释一下这个问题吗?

你的分析是正确的——一个显式专门化的函数模板,它的任何模板参数都用显式的值指定,从而提供了函数的完整定义。

如果你已经正确地将相应的包含显式专门化定义的.cpp文件包含到你的项目中,那么vc++应该不会引发链接器错误。但是,为了符合标准,请允许我注意,您必须在封闭类的之外声明您的专门化。标准禁止在封闭类内部声明显式特化(并且其他编译器将拒绝您的代码)。因此,将头文件更改为像这样声明专门化,而不是

class VariableManager
{
public:
    template<typename VarT>
        VarT get(std::string const& name) const
        {
                    // Some code...
        }
private:
    std::map<std::string, boost::any> mVariables;
};
// This method supposed to be fully evaluated, linkable method.   
template<>
std::string VariableManager::get<std::string>(std::string const& name) const;

让我也注意到,你不能在你的类体内调用get<std::string>。这是因为任何这样的调用都还没有看到显式专门化声明,因此会尝试从模板定义实例化函数。标准将这样的代码呈现为错误格式,而不需要进行诊断。

专门化模板不会强制编译器实例化它(我认为GCC会这样做);您仍然需要显式地告诉编译器实际实例化模板。可以通过显式模板实例化来实现。基本上,只需在源文件中添加以下内容:

template std::string VariableManager::get(const std::string& name) const;

template<>开头的方法仍然被认为是template 专门化方法。所以你必须把它放入头文件。

如果你想把它放到一个实现文件中,那么你必须重载它。

class VariableManager
{
//...
  VarT get(std::string const& name) const
  {}
  std::string get(std::string const& name) const; //overloading not specialization
};
相关文章: