【问题标题】:Why does including a header cause a "use of auto before deduction of auto" error?为什么包含标题会导致“在扣除自动之前使用自动”错误?
【发布时间】:2017-05-25 19:39:34
【问题描述】:

我已经完成了我正在处理的项目并将其缩短为三个简短的文件,以复制正在发生的事情。我正在使用 2011 标准下的 g++ 使用 Code::Blocks IDE。

文件是main.cppthing.cppthing.h。标头 (.h) 具有声明,源 (.cpp) 具有实现。 thing 文件使用模板参数T 定义了一个类ThingThing 所做的只是持有一个 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&lt;S&gt;&amp; s, const Thing&lt;T&gt;&amp; t); 才能使用的auto。它需要代码。
  • @WhozCraig 为什么调用者只能访问标头而不能访问源文件中的实现?实际上,调用者在其他情况下如何访问源?我的印象是,当函数被调用时,编译器会在实现中进行替换,其中可以推导出自动返回类型。
  • 编译器无法做到这一点,因为当您要使用它时,它需要手头的模板定义。 Main是翻译单元,Thing是另一个翻译单元,Thing的模板类定义在main TU中不存在。
  • @StoryTeller:不,这不是原因。请更加小心你的dupehammer。
  • @MárioFeroldi 我想我理解这个问题。我的印象是auto 扣除导致了问题,而这实际上是模板恶作剧。删除行 auto c = a + b; 会导致新的不同错误 (undefined reference to Thing&lt;int&gt;::Thing(etc...))。我认为auto 是罪魁祸首,因为这些新错误在包含时没有出现,并且构建过程通常会在代码中吐出所有错误的列表。

标签: c++ templates operator-overloading header-files auto


【解决方案1】:

推导返回类型是在 C++14 中引入的。

科利鲁reproduces your problem in C++11 mode,但shows the code working in C++14

当然,虽然这不是您的问题的直接原因,it is likely that you will have to move your template definitions into the/a header

哦,这是您应该用来测试的 minimal 测试用例:

template <typename T>
auto foo(T a)
{
    return a;
}

int main()
{
    foo(42);
}

【讨论】:

  • 他们自己承认,当包含thing.cpp 而不是 thing.h 时,该代码适用于 OP。所以这不是 C++11 与 C++14 的问题。它是一个不在标题问题内定义的模板。这只会使您的答案中的链接相关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-09
相关资源
最近更新 更多