yohhoyの日記

技術的メモをしていきたい日記

auto as ラムダ式の戻り値型

C++14以降では、ラムダ式の戻り値型(trailing-return-type)としてautoキーワードを指定できる。*1

// C++11ではNG/C++14以降はOK
auto f = [](int a, int b) -> auto {  // int型に推論
  return a + b;
};

auto h = [](auto& v) -> decltype(auto) { return v; };
int i = 42;
int &ri = h(i);  // int&型に推論

C++14 5.1.2/p4, 7.1.6.4/p1より引用(下線部は強調)。

4 If a lambda-expression does not include a lambda-declarator, it is as if the lambda-declarator were (). The lambda return type is auto, which is replaced by the trailing-return-type if provided and/or deduced from return statements as described in 7.1.6.4. [Example:

auto x1 = [](int i){ return i; }; // OK: return type is int
auto x2 = []{ return { 1, 2 }; };
  // error: deducing return type from braced-init-list
int j;
auto x3 = []()->auto&& { return j; }; // OK: return type is int&

-- end example]

1 The auto and decltype(auto) type-specifiers designate a placeholder type that will be replaced later, either by deduction from an initializer or by explicit specification with a trailing-return-type. The auto type-specifier is also used to signify that a lambda is a generic lambda.

C++14に採択された、同機能の追加提案を含むN3638より一部引用。

auto in trailing-return-type
This proposal initially did not allow auto in a trailing-return-type, but since then it was pointed out that putting it there is the only way to specify that a lambda returns by a deduced reference type:

[]()->auto& { return f(); }
N3638 Return type deduction for normal functions

関連URL

*1:C++14で追加された、ラムダ式のパラメータ型にautoキーワードを指定できるジェネリックラムダ(generic lambda)とは無関係。重箱の隅つつき...