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;
}
これはコンパイラのバグですか、それとも新しい機能ですか?
興味深いことに、「typeid」は「FA5_ivE」を返しますが、これは「int (()) [5]
」としてデマングル化されており、これはまさにあなたが考えているとおり、5 つの int の配列を返す関数を意味します。
編集: 返された配列を右辺値参照にバインドしようとしましたが、成功しませんでした (可能な形式のほとんどを使用しました)。
auto &&refArrayTemp{ func() };
この拡張機能はあまり役に立たないようです。
ベストアンサー1
これはgcc のバグ(修理済み2017-07-03現在) は、末尾の戻り値の型の処理に一貫性がないために発生します。
まず、関数を返す関数を宣言する 2 つの試みの間のエラー メッセージの違いに注目してください。
using Fv = void();
Fv f1(); // error: 'f1' declared as function returning a function
auto f2() -> Fv; // error: function return type cannot be function
最初のエラーはdecl.c
、宣言子の扱い、2番目は内部のより深いところまで、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
実際、あなたのコードも次の場所で拒否されます-Wpedantic
:
warning: ISO C++ forbids subscripting non-lvalue array
最後に、同様のバグ(末尾の戻り値の型を処理する前にスカラーから修飾子が削除される)を利用することで、次の型の関数を作成できますint const volatile()
。
int const volatile g1(); // warning: type qualifiers ignored on function return type
auto g2() -> int const volatile; // OK!!