我使用
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);
那么,我在这里错过了什么?
如果需要具有未推导占位符类型的实体类型 为了确定表达式的类型,该程序是格式错误的。 一旦在函数中看到未丢弃的 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
的情况下,这通常是通过将定义移到使用点之前来实现的。如果您实际上不需要使用返回类型推导,如果您在声明中提供签名(包括返回类型),则可以在使用后保留定义。
Clang 有一个更好的错误消息:
main.cpp:8:16: error: function 'func' with deduced return type cannot be used before it is defined
auto ret = func(5);
^
我想这是不言自明的。
当
auto
在不使用尾随返回类型语法的函数声明中用作返回类型时,关键字 auto
表示将从其 return 语句的操作数推导出返回类型。这意味着在函数func()
定义之前无法执行推导,但在此之前它已在main()
中使用过。
您可以将定义移到
main()
之前,或者使用尾随返回类型语法在声明上指定返回类型。
在您的示例中,确实没有理由不能将函数的实现移到
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 func = [](int i)
{
// ... do something with `i` ...
if(i > 0)
{
func(i - 1); // <-- same error here
}
}
auto ret(func(5));
return 0;
}
通话
func(i - 1)
有问题。要修复它,您必须将 auto
替换为实际类型:
int main()
{
typedef std::function<void(int)> func_t;
func_t func = [](int i)
{
...
如果你真的想要一个支持不同返回类型的函数,你无论如何都想使用模板,而不是
auto
。这实际上只是为了帮助您减少输入,而不是允许“任何类型”的方法。