非模板类的模板构造函数出现问题[重复]

Posted

技术标签:

【中文标题】非模板类的模板构造函数出现问题[重复]【英文标题】:Trouble with template constructor of non-template class [duplicate] 【发布时间】:2014-07-23 19:41:43 【问题描述】:

在寻找另一个question 的答案时,我开发了一个辅助类,它可以处理任何类型的整数容器。具体来说,我的班级将根据某些标准查找容器值。为了使用不同类型的容器,我的课程显然不需要对容器本身进行操作,而是对其迭代器进行操作。我不需要在我的类中的任何地方引用容器,我只使用迭代器并且只在类构造函数中使用。

// 头文件。

 class MyLookup 
    public: 
    template<typename ForwardIt>   // Forward iterator though sequence of integers
    MyLookup(ForwardIt begin, ForwardIt end)
    ...
 

// 实现文件

 template<typename ForwardIt>
 MyLookup::MyLookup(ForwardIt begin, ForwardIt end) 
 ...
 

// 使用文件

std::vector<int> foo;
...
MyLookup lookup(foo.begin(), foo.end());

使用 CLang 时,初始编译器通过成功,但随后出现链接器错误:

架构 x86_64 的未定义符号: “MyLookup::MyLookup >(std::__1::__wrap_iter, std::__1::__wrap_iter)”,引用自:...

知道我做错了什么吗?

【问题讨论】:

模板不能不在 .cpp 文件中。将文件的实现放在.hpp中。 你需要将实现放在类定义所在的头文件中。 @NetVipeC +1 表示他的问题,但这是不准确的。模板通常不在 C++ 文件中,因为它们需要在构建时完整实现。但是导出的模板特化和仅在一个编译单元中需要的模板可以在 C++ 文件中。它非常罕见。 @NetVipeC 好吧,更具体地说,模板声明和定义必须驻留在同一个文件中。所以如果你想在多个地方使用它,都需要在标题中。 @aruisdante "same file" ==> "same translation unit",我同意(无法承受显式实例化,这是 方式这个OP的问题)。 【参考方案1】:

您需要在头文件中提供模板的定义,而不是在它们自己的源文件中。这是因为模板实际上是类定义的模板——它们本身不是类定义。

【讨论】:

将三个不同的人已经在 cmets 中放置的内容放入一个答案中而不添加任何其他信息至少可以说是一种糟糕的形式。 抱歉,我回答了这个问题并提供了一些额外的概念信息,说明为什么模板实现不驻留在它们自己的源文件中。所以我不明白为什么我不把这个作为答案。 将构造函数定义移动到头文件确实解决了这个问题。我可能很困惑,因为我确实在 cpp 文件中定义了模板定义的实例。这些示例必须与 cmets 中提到的原始问题相关的案例。老实说,这已经是我第二次被标题/实现/模板问题绊倒了。谢谢大家。 @aruisdante 这不应该意味着没有人可以回答这个问题了。我经常想知道为什么人们以 cmets 的形式给出答案。

以上是关于非模板类的模板构造函数出现问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在模板类之外定义构造函数[重复]

带有模板的类的构造函数

非模板 std::reference_wrapper 赋值运算符和模板构造函数

C ++:为构造函数使用模板[重复]

将模板类实例传递给另一个类的构造函数

为啥标准不将模板构造函数视为复制构造函数?