GCC では関数から配列を返すことができます - バグか機能か? 質問する

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;
}

これはコンパイラのバグですか、それとも新しい機能ですか?

興味深いことに、「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!!

おすすめ記事