【发布时间】:2017-05-25 19:39:34
【问题描述】:
我已经完成了我正在处理的项目并将其缩短为三个简短的文件,以复制正在发生的事情。我正在使用 2011 标准下的 g++ 使用 Code::Blocks IDE。
文件是main.cpp、thing.cpp 和thing.h。标头 (.h) 具有声明,源 (.cpp) 具有实现。 thing 文件使用模板参数T 定义了一个类Thing。 Thing 所做的只是持有一个 T 类型的对象(它基本上什么都不做)。
main.cpp:
#include <iostream>
#include "thing.h"
int main(){
Thing<int> a(9);
Thing<double> b(3.2);
auto c = a + b;
c.display();
return 0;
}
thing.h:
#ifndef THING_H
#define THING_H
template<typename T>
class Thing{
private:
T content;
public:
Thing(const T& content);
~Thing(){};
T get_content() const;
void display();
};
template<typename S, typename T>
auto operator+(const Thing<S>& s, const Thing<T>& t);
#endif // THING_H
thing.cpp:
#include "thing.h"
#include <iostream>
template<typename T>
Thing<T>::Thing(const T& content)
:content(content){}
template<typename T>
void Thing<T>::display(){
std::cout << content << '\n';
}
template<typename T>
T Thing<T>::get_content() const {
return content;
}
template<typename S, typename T>
auto operator+(const Thing<S>& s, const Thing<T>& t){
S s_content = s.get_content();
T t_content = t.get_content();
Thing<typename std::common_type<S, T>::type> sum = s_content + t_content;
return sum;
}
这是奇怪的行为:代码是否编译取决于#include "thing.h" 行。这里使用thing.h会编译不出来,导致报错:
error: use of 'auto operator+(const Thing<S>&, const Thing<T>&) [with S = int; T = double]' before deduction of 'auto'
error: invalid use of 'auto'
将此行更改为#include "thing.cpp" 允许代码编译没有问题并按预期运行(它将12.2 输出到控制台)。
我的问题是:编译器在这两种情况下有何不同? including header 时如何更改代码以消除此错误?
提前致谢。
【问题讨论】:
-
您可能还应该首先问自己why you're not implementing your templates in a header?调用者不可能推断出只有
auto operator+(const Thing<S>& s, const Thing<T>& t);才能使用的auto。它需要代码。 -
@WhozCraig 为什么调用者只能访问标头而不能访问源文件中的实现?实际上,调用者在其他情况下如何访问源?我的印象是,当函数被调用时,编译器会在实现中进行替换,其中可以推导出自动返回类型。
-
编译器无法做到这一点,因为当您要使用它时,它需要手头的模板定义。 Main是翻译单元,Thing是另一个翻译单元,
Thing的模板类定义在main TU中不存在。 -
@StoryTeller:不,这不是原因。请更加小心你的dupehammer。
-
@MárioFeroldi 我想我理解这个问题。我的印象是
auto扣除导致了问题,而这实际上是模板恶作剧。删除行auto c = a + b;会导致新的不同错误 (undefined reference to Thing<int>::Thing(etc...))。我认为auto是罪魁祸首,因为这些新错误在包含时没有出现,并且构建过程通常会在代码中吐出所有错误的列表。
标签: c++ templates operator-overloading header-files auto