Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 链接时模板专门化失败_C++_Templates_Visual C++ - Fatal编程技术网

C++ 链接时模板专门化失败

C++ 链接时模板专门化失败,c++,templates,visual-c++,C++,Templates,Visual C++,我有一个模板专门化的问题,我想了解。我用Visual C++ 10(2010)工作。我有一门课是这样的: class VariableManager { public: template<typename VarT> VarT get(std::string const& name) const { // Some code... } // This method sup

我有一个模板专门化的问题,我想了解。我用Visual C++ 10(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;
};
类变量管理器
{
公众:
模板
VarT get(std::string const&name)const
{
//一些代码。。。
}
//这种方法应该是全面评估的、可链接的方法。
模板
std::string get(std::string const&name)const;
私人:
映射多变量;
};
理论上,因为我专门使用了“get”方法,所以链接器应该能够从对象文件中提取。相反,如果我将方法放在源文件中,则链接器会出现未解决的引用错误:

    template<>
    std::string VariableManager::get<std::string>(std::string const& name) const
            {
                 // Doing something...
            }
template std::string VariableManager::get(const std::string& name) const;
模板
std::string VariableManager::get(std::string const&name)const
{
//做点什么。。。
}
如果我将此方法作为内联方式放在头文件中,则构建过程会很顺利。我理解模板的功能如下:

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

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

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

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

模板
开始的方法仍然被认为是
模板
专门化方法。因此,您必须将其放入头文件中

如果要将其放入实现文件中,则必须重载它

class VariableManager
{
//...
  VarT get(std::string const& name) const
  {}

  std::string get(std::string const& name) const; //overloading not specialization
};

您的分析是正确的-具有使用显式值指定的任何模板参数的显式专用函数模板提供了函数的完整定义

如果已将包含显式专门化定义的相应
.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;
类变量管理器
{
公众:
模板
VarT get(std::string const&name)const
{
//一些代码。。。
}
私人:
映射多变量;
};
//这种方法应该是全面评估的、可链接的方法。
模板
std::string VariableManager::get(std::string const&name)const;

我还要指出,您不能在类主体内部调用
get
。这是因为任何这样的调用都不会看到显式的专门化声明,因此会尝试从模板定义实例化函数。该标准使此类代码格式不正确,不需要进行诊断。

不,您不需要。见雷科的回答。我不确定你所说的“模板专门化方法”是什么意思(但我建议你在任何一天都要对专业化进行重载!)@Tomalak,OP正试图专门化问题中的
模板
方法
获取
。我的答案是,应该在头文件中声明专门的方法。“你能详细说明一下吗,怎么了?”iammilind:看看利特的答案,他解释得很好。他所做的模板专门化的问题是,实际上不允许这样做。显式专门化必须在名称空间范围内完成,但由于某些原因,MSVC没有给出类范围内专门化的错误。如果他做得正确,即使代码不在头文件中,也可以正常工作。这就是你的答案的错误所在;您不需要在头中包含代码,因为显式专门化实际上不是一个模板,只是一个常规函数。这是错误的。他专门化了它,所以他不需要也不想实例化templatelitb是正确的,这确实是错误的,但我将在这里留下我的答案,以便其他人可以看到它是错误的,这很有趣,但似乎标准遵从性问题就是问题所在。我从类中删除了声明,并按照您的建议进行了专门化声明,链接器没有任何问题。最好记住,专门化必须在类的作用域之外声明。谢谢你的帮助!找到你的答案对我来说真是幸运。对于我来说,如果我将模板专门化留在类中,编译器会做什么,以及是什么使链接器无法找到它,这仍然是一个谜。然而,你确实救了我一天!