模板方法的未定义引用错误

时间:2009-07-10 19:13:32

标签: c++ templates compilation linker

在过去的一个半小时里,这让我很生气。我知道这是一件小事,但找不到什么是错的(事实上,这是一个下雨的星期五下午,当然,没有帮助。)

我已经定义了以下类,它将保存从文件中读取的配置参数,并允许我从我的程序中访问它们:

class VAConfig {
    friend std::ostream& operator<<( std::ostream& lhs, const VAConfig& rhs);

private:
    VAConfig();
    static std::string      configFilename;
    static VAConfig*        pConfigInstance;
    static TiXmlDocument*   pXmlDoc;
    std::map<std::string, std::string> valueHash;

public:
    static VAConfig* getInstance();
    static void setConfigFileName( std::string& filename ) { configFilename = filename; }
    virtual ~VAConfig();

    void readParameterSet( std::string parameterGroupName );
    template<typename T> T readParameter( const std::string parameterName );
    template<typename T> T convert( const std::string& value );
};

方法convert()VAConfig.cpp中定义为

template <typename T>
T VAConfig::convert( const std::string& value )
{
    T t;
    std::istringstream iss( value, std::istringstream::in );
    iss >> t;
    return t;
}

一切都很简单。但是当我使用

从我的主程序进行测试时
int y = parameters->convert<int>("5");

我收到undefined reference to 'int VAConfig::convert<int>...'编译错误。同上readParameter()

看了很多模板教程,但不能弄清楚这一点。有什么想法吗?

3 个答案:

答案 0 :(得分:68)

模板化代码实现永远不应该在.cpp文件中:您的编译器必须在看到调用它们的代码的同时看到它们(除非您使用explicit instantiation生成模板化对象代码,但即便如此.cpp是要使用的错误文件类型。

您需要做的是将实现移动到头文件,或者移动到VAConfig.t.hpp等文件,然后在使用任何模板化成员函数时移动#include "VAConfig.t.hpp"

答案 1 :(得分:10)

如果将模板化方法(convert和readParameter)的实现移动到头文件,它应该可以工作。

编译器必须能够在实例化它们的位置访问模板化函数的实现。

答案 2 :(得分:5)

模板方法仅仅是方法的...模板。模板参数将填入“实例化”方法的位置。

应该可以构建一个满足模板方法声明的编译器,并使用“模板编译”步骤编译模板方法的所有必需实例。

微软的vc不是这种情况。不过,我听到一位同事在unix上嘀咕道。

大多数编译器根据请求实例化模板方法,在源代码中使用它们。为了实例化该方法,编译器必须“看到”模板函数体。这就是为什么身体最常被放置在头文件中,或者例如放在头文件中的原因。一个.h.cpp文件,然后包含在.h文件的最后一行。