G++ 模板实例化导致“未定义引用”错误

G++ Template instantiation results in "Undefined reference to" error

提问人: 提问时间:6/1/2015 最后编辑:Cameron Tacklind 更新时间:4/22/2021 访问量:1111

问:

我最近在使用自定义编写的通用向量代码时遇到了一些问题,该代码依赖于模板来实现功能。我不愿意将实现包含在头文件中(这在模板中很常见),因为这会大大增加编译时间。因此,我在 .cpp 文件中手动实例化了所需的类。但是,这仍然会导致未定义的引用错误。我已将代码简化为以下代码片段,这仍然会产生错误:

矩阵.cpp

#include "matrixd.h"

namespace math
{
    template class _vec2<float>;
    template<class T> _vec2<T>::_vec2() {}
}

矩阵.h

#pragma once
namespace math
{ 
    template <class T>
    class _vec2
    {
    public:
        T x, y;
        _vec2<T>();
        void reset();
    };

    typedef _vec2<float> vec2;
}

测试.cpp

#include "matrixd.h"

int main()
{
    math::_vec2<float> v;
}

错误信息:

在函数 math::_vec2::_vec2()' collect2 中:错误:ld 返回 1 个退出 地位main': source.cpp:(.text+0x10): undefined reference to

任何帮助将不胜感激!:)

C 模板 G++ 未定义引用

评论

0赞 6/1/2015
你好!如果这是重复的,您能指导我找到适当的解决方案吗?我看到了类似的问题,但发帖人遇到的问题是他们不知道手动模板实例化。
0赞 Jonathan Wakely 6/1/2015
要声明构造函数,您只需要编写 not_vec2()_vec2<T>()
0赞 Jonathan Wakely 6/1/2015
您可以将定义放在头文件中,并在标头中添加显式实例化声明(即“外部模板”声明),该声明告诉编译器它不需要实例化成员,因为您将在某些翻译单元中提供显式实例化定义(在本例中为 matrixd.cpp)
0赞 T.C. 6/1/2015
@JonathanWakely我相信两者都是合法的,尽管绝对更干净。_vec2()
1赞 David Hammen 6/1/2015
我对模板的一般建议:如果可能的话,不要使用源文件来定义模板函数。相反,使模板成为仅标头实现。它使生活变得更加轻松。关于前导下划线:也不要那样做。仅仅因为标准库使用前导下划线并不意味着您应该这样做。事实上,这意味着你不应该这样做。标准库使用前导下划线来避免与用户代码冲突。虽然在这种情况下是合法的,但带有前导下划线的用户代码不是一个好的做法。_vec2

答:

5赞 T.C. 6/1/2015 #1

显式实例化定义(在代码中)仅实例化在显式实例化时定义的成员函数。 是在显式实例化定义之后定义的,因此未显式实例化。template class _vec2<float>;_vec2<T>::_vec2()

解决方法是交换两行:

namespace math
{
    template<class T> _vec2<T>::_vec2() {}
    template class _vec2<float>;
}

评论

0赞 6/1/2015
这。。。只是为我节省了几个小时。谢谢!