【问题标题】:Use of 'auto func(int)' before deduction of 'auto' in C++14在 C++14 中扣除 'auto' 之前使用 'auto func(int)'
【发布时间】:2017-09-16 19:13:19
【问题描述】:

我使用C++14 在 GCC 中编译了以下程序。

#include <iostream>
using namespace std;

auto func(int i);

int main() 
{
    auto ret = func(5);
    return 0;
}

auto func(int i) 
{
  if (i == 1)
    return i;              
  else
    return func(i-1) + i;  
}

但是,我收到以下错误。

In function 'int main()': 8:16: error: use of 'auto func(int)' before
deduction of 'auto'
 auto ret = func(5);

那么,我在这里错过了什么?

【问题讨论】:

  • 请记住,C++ 是为一次性编译器设计的(许多编译器仍然如此)。 ret 的扣除取决于 func,但在执行单遍翻译时尚不可用。
  • 你认为应该给func什么返回类型,为什么?
  • @n.m.返回类型 int 因为 func() 返回 1 到 n 个数字的总和。
  • 直到现在我才意识到您问题中的功能与标准中示例中的功能相同...这是巧合吗?因为如果不是,那么您只是错过了示例的第 2 行和第 3 行。 (是的,我确实意识到这是一个非常常见的递归方案。只是确保。)
  • 糟糕,我的错误,请忽略。

标签: c++ function gcc c++14 auto


【解决方案1】:

这是[dcl.spec.auto/11]:

如果需要具有未推断占位符类型的实体类型 要确定表达式的类型,程序格式错误。 一旦在函数中看到未丢弃的 return 语句, 但是,从该语句推导出的返回类型可以用于 函数的其余部分,包括在其他 return 语句中。 [ 示例:

auto n = n;                     // error, n's type is unknown
auto f();
void g() { &f; }                // error, f's return type is unknown
auto sum(int i) {
  if (i == 1)
    return i;                   // sum's return type is int
  else
    return sum(i-1)+i;          // OK, sum's return type has been deduced
}

 — 结束示例 ]

要将其翻译成英文:编译器需要知道返回类型才能使用该函数。如果像这样使用auto,这通常是通过在使用点之前移动定义来实现的。如果您实际上不需要使用返回类型推导,您可以在声明中提供签名,包括返回类型,使用后保留定义。

【讨论】:

  • 爱他们的标准报价。
  • 直截了当,很好的答案!我认为还值得一提的是,即使在这种情况下,即使f 在main 之后定义,编译器也应该能够神奇地推断返回类型,但当f 的定义为在单独的翻译单元中:在这种情况下,编译器很难弄清楚发生了什么。
【解决方案2】:

Clang 有一个更好的错误消息:

main.cpp:8:16: error: function 'func' with deduced return type cannot be used before it is defined
    auto ret = func(5);
               ^

我想这是不言自明的。

【讨论】:

  • 顺便说一句,我想这就是 H-M 推理真正能够跳过它、得到定义,然后正确检查的地方。
  • 爱他们的铿锵语录。
【解决方案3】:

当auto 用作不使用尾随返回类型语法的函数声明中的返回类型时,关键字auto 表示将从其返回语句的操作数推导出返回类型。这意味着在定义函数func()之前不能进行推演,但在此之前它已经在main()中使用过。

您可以将定义移到main() 之前,或使用尾随返回类型语法在声明中指定返回类型。

【讨论】:

    【解决方案4】:

    在您的示例中,您确实没有理由不能将函数的实现移到 main() 之前:

    #include <iostream>
    using namespace std;  // you should avoid this, too
    
    auto func(int i)
    {
      if (i == 1)
        return i;
      else
        return func(i-1) + i;
    }
    
    int main()
    {
        auto ret = func(5);
        return 0;
    }
    

    否则,您将无法使用 auto 关键字。特别是,您不能在不返回任何内容的递归函数中使用 auto 。你必须使用void。这适用于 lambda 函数。例如:

    int main()
    {
        auto f = [](int i)
        {
            // ... do something with `i` ...
            if(i > 0)
            {
                f(i - 1);   // <-- same error here
            }
        }
    
        auto ret(func(5));
        return 0;
    }
    

    电话f(i - 1)有问题。要修复它,您必须将 auto 替换为实际类型:

    int main()
    {
        typedef std::function<void(int)> func_t;
        func_t f = [](int i)
        {
        ...
    

    如果你真的想要一个支持不同返回类型的函数,无论如何你都想使用模板,而不是auto。这实际上只是为了帮助您减少打字,而不是允许“任何类型”的方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-24
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      • 2017-02-16
      • 1970-01-01
      相关资源
      最近更新 更多