GCC允许从函数返回数组 - 错误或功能?

AnA*_*ons 27 c++ arrays gcc

我惊讶地发现,当使用尾随返回类型而不是正常返回类型时,GCC允许函数返回数组.你可能知道数组不能被复制所以这是非常有限的,但让我向你展示一些很酷的例子.

#include <iostream>
#include <typeinfo>

using namespace std;

auto func() -> int [5]
{
    return {4, 56, 78, 4, 0};
}

int main()
{
    cout << func()[2] << endl;
    cout << typeid(func).name() << endl;
}
Run Code Online (Sandbox Code Playgroud)

这是编译器错误还是一些新功能?

有趣的是'typeid'返回'FA5_ivE',它被解析为' int (()) [5]',这意味着你认为函数返回5个int的数组.

编辑:我尝试将返回的数组绑定到右值引用但没有任何成功(使用大多数可能的形式):

auto &&refArrayTemp{ func() };
Run Code Online (Sandbox Code Playgroud)

似乎这种扩展是无用的.

eca*_*mur 13

这是gcc中的一个错误(2017-07-03修复),由跟踪返回类型的不一致处理引起.

首先注意两次尝试声明返回函数的函数之间的错误消息的差异:

using Fv = void();
Fv f1();             // error: 'f1' declared as function returning a function
auto f2() -> Fv;     // error: function return type cannot be function
Run Code Online (Sandbox Code Playgroud)

第一个错误来自decl.c处理声明者,而第二个错误来自内部,更深入到内部tree.c,尝试构建函数类型准备生成代码.

尾随返回类型在decl.c中处理30行以上错误 - 太晚了,无法用上面的错误代码捕获它,并且它不是单独处理的.

对于数组,类似地使用trailing-return-type允许我们跳过检查decl.c,不同之处在于function-returning-array实际上在gcc的内部表示方面是有效的.

请注意,你不能做太多的事情; gcc不允许您分配,引用绑定,衰减或将结果传递func()给另一个函数:

auto a1 = func();
// error: invalid use of non-lvalue array

auto& a2 = func();
// error: invalid initialization of non-const reference of type 'int (&)[5]' from an rvalue of type 'int [5]'

auto&& a3 = func();
// error: lvalue required as unary '&' operand
Run Code Online (Sandbox Code Playgroud)

实际上,即使您的代码也被拒绝-Wpedantic:

warning: ISO C++ forbids subscripting non-lvalue array
Run Code Online (Sandbox Code Playgroud)

最后,通过利用类似的bug(在处理trailing-return-types之前从标量中删除限定符),我们可以创建一个类型为的函数int const volatile():

int const volatile g1();          // warning: type qualifiers ignored on function return type
auto g2() -> int const volatile;  // OK!!
Run Code Online (Sandbox Code Playgroud)

  • @FISOCPP你已经可以了.`std :: array`比内置的C风格数组更好. (6认同)
  • @FISOCPP哦不,你没有!"腐烂指针,忘记大小"是世界上最可怕的事情.到处使用`std :: array`.如果你不讨厌自己,那就是你应该使用的东西. (4认同)

0x4*_*2D2 8

最新稿,[dcl.array]/p10:

函数不应具有类型数组或函数的返回类型,尽管它们可能具有类型指针的返回类型或对此类事物的引用.虽然可以有函数指针数组,但是不应该有函数数组.

这可能是非标准的GCC扩展.它不能在clang的trunk版本中编译.但是,这也可能是一个错误,因为它与非尾随返回类型的行为不一致.