在 C++14 中推导 'auto' 之前使用 'auto func(int)'

Use of 'auto func(int)' before deduction of 'auto' in C++14

我使用 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);

那么,我在这里缺少什么?

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

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

我想这是不言自明的。

auto 在不使用尾随 return 类型语法的函数声明中用作 return 类型时,关键字 auto 表示 return 类型将从其 return 语句的操作数中推导出来。也就是说在函数func()的定义之前不能进行推导,但在此之前它已经在main().

中使用过

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

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

If the type of an entity with an undeduced placeholder type is needed to determine the type of an expression, the program is ill-formed. Once a non-discarded return statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other return statements. [ Example:

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
}

 — end example ]

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

在你的例子中,你真的没有理由不能在 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关键字。特别是,您不能在没有 return 任何东西的递归函数中使用 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)
    {
    ...

如果您真的想要一个支持不同 return 类型的函数,您无论如何都想使用模板,而不是 auto。这实际上只是为了帮助您减少打字,而不是允许 "any type".