web-dev-qa-db-ja.com

ラムダの戻り値の型は戻り値から推定できるので、なぜ関数の戻り値はできないのでしょうか?

#include <iostream>

int main(){

    auto lambda = [] {
        return 7;
    };

    std::cout << lambda() << '\n';

}

このプログラムはコンパイルして7を出力します。
ラムダの戻り値の型は、戻り値7に基づいて整数型に推定されます。


通常の関数でこれができないのはなぜですか?

#include <iostream>

auto function(){
    return 42;
}

int main(){

    std::cout << function() << '\n';
}

エラー: ‘関数’関数は、末尾の戻り値型なしで「自動」型指定子を使用します

75
Trevor Hickey

C++ 14にはこの機能があります-std=c++1yフラグを設定すると、GCCまたはclangの新しいバージョンでテストできます。

実例

それに加えて、C++ 14では、関数にdecltype(auto)(変数のdecltype(auto)を反映)を使用して、decltypeセマンティクスを使用して戻り値を推定することもできます。 。

例は、decltype(auto)が特に役立つ転送機能の場合です。

template<typename function_type, typename... arg_types>
decltype(auto) do_nothing_but_forward(function_type func, arg_types&&... args) {
    return func(std::forward<arg_types>(args)...);
}

decltype(auto)を使用すると、指定した引数で呼び出されたときに、funcの実際の戻り値の型を模倣します。 C++ 11では非常にイライラし、エラーが発生しやすい、末尾の戻り値型のコードの重複はなくなりました。

77
Mark Garcia

これは、言語がどのように作成され、進化したかの制限にすぎません。今後のC++ 14標準では、関数の戻り値の型は、すべてではありませんが、一部のコンテキストで推定できます。複数のreturnステートメントがある場合、複雑になります。

さらに、推定される戻り値の型には他の問題があります。たとえば、テンプレート関数の戻り値の型は [〜#〜] sfinae [〜#〜] コンテキストでは使用できないため、推定できますタイプ、コンパイラは関数テンプレートをインスタンス化する必要があります。これはafter置換の後に行われます。最終的には、この機能は近い将来に存在することになりますが、自分でタイプを提供できる場合は、それを避けます。

これはc ++ 14で提供されます。次の proposal を参照してください。

10
user425495

まだそこにはありません。C++ 1y/C++ 14に含まれる予定です。これをチェックしてください 機能のリンク

6
Hitesh Vaghani

私の推測では、それはおそらく型推論されたラムダは再帰的ではないが原因です。

なぜこれが問題なのですか?型推論されたラムダが再帰的である可能性がある場合(「型推論」とは、変数の名前がauto型である場合を意味します)、その戻り値の型は、それ自体に依存する可能性があります。解決することは可能ですが、「単純な」型推論よりも実装がはるかに困難です。それがalways解決可能であるかどうかさえわかりません(一般的なケースでは決定可能ですか?)。ただし、関数が型推論をサポートしている場合は、この問題に対処する必要があるため、この理由で除外された可能性があります。

5
Mehrdad