#include <vector>
#include <algorithm>
void foo( int )
{
}
int main()
{
std::vector< int > v( { 1,2,3 } );
std::for_each( v.begin(), v.end(), []( auto it ) { foo( it+5 ); } );
}
コンパイルすると、上記の例は次のようにエラー出力を開始します。
h4.cpp: In function 'int main()':
h4.cpp:13:47: error: parameter declared 'auto'
h4.cpp: In lambda function:
h4.cpp:13:59: error: 'it' was not declared in this scope
キーワードauto
をラムダ式で使用しないでください。
これは動作します:
std::for_each( v.begin(), v.end(), []( int it ) { foo( it+5 ); } );
Autoキーワードを含むバージョンが機能しないのはなぜですか?
c ++ 11では、autoキーワードは関数引数の型として機能しません。ラムダ関数で実際の型を使用したくない場合は、以下のコードを使用できます。
for_each(begin(v), end(v), [](decltype(*begin(v)) it ){
foo( it + 5);
});
問題のコードは、C++ 14では問題なく動作します。
C++ 14では、ラムダ関数(ジェネリックラムダ関数)パラメーターをautoで宣言できます。
auto multiply = [](auto a, auto b) {return a*b;};
これは、インタビュー中にHerb Sutterによって簡単に議論されました。 auto
引数に対する要求は、実際にはany関数がauto
で次のように宣言可能であることを要求することと同じです。
auto add(auto a, auto b) -> decltype(a + b) { return a + b; }
ただし、これは実際には関数ではなく、template関数であり、次のようなものです。
template <typename S, typename T>
auto add(S a, T b) -> decltype(a + b) { return a + b; }
したがって、本質的には、引数を変更することによって任意の関数をテンプレートに変換する機能を求めています。テンプレートはC++の型システムでは非常に異なる種類のエンティティであるため(2フェーズルックアップや演繹など、テンプレートのすべての特別なルールを考えてください)、これは予期せぬ影響を伴う根本的な設計変更となります。 tいつでも規格に入る予定です。
コンパイラがstd::for_each
をインスタンス化する前に、ラムダのタイプを知っておく必要があります。一方、理論的には可能であるとしても、ファンクターがどのように呼び出されるかを確認することによってfor_each
がインスタンス化された後にのみ、そのauto
を推定できます。
可能であれば、for_each
を忘れて、範囲ベースのforループを使用してください。
for (int it : v) {
foo(it + 5);
}
これはauto
(およびauto&
とconst auto&
)にもうまく対応するはずです。
for (auto it : v) {
foo(it + 5);
}