[C++] ๋žŒ๋‹ค ํ‘œ์ค€

๋ถ€์กฑํ•œ ์‹ค๋ ฅ์ด๋‚˜๋งˆ ๋ฒˆ์—ญ์„ ์ข€ ํ•ด๋ณด์•˜๋Š”๋ฐ.. ์ง€์ ์ด๋‚˜ ์กฐ์–ธ ๊ฐ์‚ฌํžˆ ๋ฐ›์Šต๋‹ˆ๋‹ค.



8.1.5 Lambda expressions
: ๋žŒ๋‹ค ํ‘œํ˜„์‹


Lambda expressions provide a concise way to create simple function objects.ย 
: ๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ์‹ฌํ”Œํ•œ ํ•จ์ˆ˜๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ์†์‰ฌ์šด ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค.


[ Example:

#include

#include

void abssort(float* x, unsigned N)
{
ใ…คstd::sort(x, x + N, [](float a, float b) { return ใ…คstd::abs(a) < std::abs(b); });
}

โ€” end example ]



2 A lambda-expression is a prvalue whose result object is called the closure object.ย 
: ๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ํด๋กœ์ € ๊ฐ์ฒด๋ฅผ ๋ถ€๋ฅธ ๊ฒฐ๊ณผ๋ฌผ๋กœ, ์ˆœ์ˆ˜ํ•œ ์˜ค๋ฅธ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

A lambda-expression shall not appear in an unevaluated operand (Clause 8), in a template-argument, in an alias-declaration, in a typedef declaration, or in the declaration of a function or function template outside its function body and default arguments.ย 
: ๋žŒ๋‹ค์‹์€ ํ‰๊ฐ€๋˜์ง€ ์•Š์€ ํ”ผ์—ฐ์‚ฐ์ž์™€, ํ…œํ”Œ๋ฆฟ์ธ์ž์™€, ์ต๋ช…๋ฒ”์œ„?(alias-declaration)์™€, typedef ์„ ์–ธ์—์„œ๋‚˜, ํ•จ์ˆ˜์˜ ์„ ์–ธ์ด๋‚˜, ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ ๋ชธ์ฒด๋‚˜, ๋””ํดํŠธ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ๋Š” ๋‚˜ํƒ€๋‚  ์ˆ˜ ์—†๋‹ค.

[ Note: The intention is to prevent lambdas from appearing in a signature. โ€” end note ]ย 
: ๊ทธ ์˜๋„๋Š” ๋žŒ๋‹ค๊ฐ€ ์‹œ๊ทธ๋„ˆ์ฒ˜์—์„œ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ์˜ˆ๋ฐฉํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค.

[ Note: A closure object behaves like a function object (23.14). โ€” end note ]
: ํด๋กœ์ € ๊ฐ์ฒด๋Š” ํ•จ์ˆ˜๊ฐ์ฒด์™€ ๋น„์Šทํ•˜๊ฒŒ ์ž‘๋™ํ•œ๋‹ค.

3 In the decl-specifier-seq of the lambda-declarator, each decl-specifier shall either be mutable or constexpr.
: ๋žŒ๋‹ค ์„ ์–ธ์ž์˜ ์„ ์–ธ๋ถ€์—์„œ ๊ฐ๊ฐ์˜ ์„ ์–ธ์ง€์ •์ž๋Š” mutable๊ณผ constexpr์„ ํ—ˆ์šฉํ•œ๋‹ค.

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 type specified by the trailing-return-type if provided and/or deduced from return statements as described in 10.1.7.4.ย 
: ๋žŒ๋‹ค์˜ ๋ฆฌํ„ดํƒ€์ž…์€ auto์ด๋‹ค.
๋งŒ์•ฝ 10.1.7.4์—์„œ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ฐ˜ํ™˜๋ฌธ์—์„œ ํƒ€์ž…์ด ์ œ๊ณต๋˜๊ฑฐ๋‚˜ ์ถ”๋ก ๋œ๋‹ค๋ฉด trailing-return-type(ํ›„ํ–‰๋ฐ˜ํ™˜ํƒ€์ž…)์— ์˜ํ•ด ์ง€์ •๋œ ํƒ€์ž…์œผ๋กœ ๊ต์ฒด๋œ๋‹ค.


[ Example:

auto x1 = [](int i){ return i; };
// OK: ๋ฆฌํ„ดํƒ€์ž…์ด int๋‹ค.
auto x2 = []{ return { 1, 2 }; };
// error: ์ค‘๊ด„ํ˜ธ์ดˆ๊ธฐ์น˜๋กœ ์ถ”๋ก ํ•œ๋‹ค.

int j;

auto x3 = [\]()->auto&& { return j; };
// OK: ๋ฆฌํ„ดํƒ€์ž…์ด int&์ด๋‹ค.

โ€” end example ]



8.1.5.1 Closure types
: ํด๋กœ์ € ํƒ€์ž…

1 The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below.
: ๋žŒ๋‹ค์‹์˜ ํƒ€์ž…์€ '์œ ์ผํ•˜๋ฉฐ'(unique),
์ด๋ฆ„์ด ์—†๊ณ  ๋ญ”๊ฐ€์— ์†ํ•ด์žˆ์ง€๋„ ์•Š์€ ํด๋ž˜์Šค ํƒ€์ž…์ด๋ฉฐ,
ํด๋กœ์ € ํƒ€์ž…์ด๋ผ๊ณ ๋„ ๋ถ€๋ฅด๋Š”๋ฐ, ์ด์— ๊ด€ํ•œ ์†์„ฑ๋“ค์€ ์•„๋ž˜์—์„œ ์„ค๋ช…ํ•œ๋‹ค.


2 The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.ย 
: ํด๋กœ์ € ํƒ€์ž…์€ ๋ถ€ํ•ฉํ•˜๋Š” ๋žŒ๋‹ค์‹์„ ํฌํ•จํ•˜๋Š” ๊ฐ€์žฅ ์ž‘์€ ๋ธ”๋Ÿญ ์Šค์ฝ”ํ”„, ํด๋ž˜์Šค ์Šค์ฝ”ํ”„, ์ด๋ฆ„๊ณต๊ฐ„ ์Šค์ฝ”ํ”„์—์„œ ์„ ์–ธ๋œ๋‹ค.

[ Note: This determines the set of namespaces and classes associated with the closure type (6.4.2).ย 
: ์ด๊ฒƒ์€ ์ด๋ฆ„๊ณต๊ฐ„์˜ ์ง‘ํ•ฉ๊ณผ ํด๋กœ์ €ํƒ€์ž…๊ณผ ๊ด€๊ณ„๋œ ํด๋ž˜์Šค๋“ค์„ ์•Œ์•„๋‚ธ๋‹ค.

The parameter types of a lambda-declarator do not affect these associated namespaces and classes. โ€” end note ]
: ๋žŒ๋‹ค ์„ ์–ธ์ž์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…๋“ค์€ ๊ด€๋ จ๋œ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋‚˜ ํด๋ž˜์Šค๋“ค์— ๋Œ€ํ•ด์„œ ์•„๋ฌด ์˜ํ–ฅ๋„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

The closure type is not an aggregate type (11.6.1).ย 
: ํด๋กœ์ € ํƒ€์ž…์€ aggregate ํƒ€์ž…์ด ์•„๋‹ˆ๋‹ค.(๋ญ”์†Œ๋ฆฐ์ง€ ๋ชจ๋ฅด๊ฒ ์Œ)

An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing:
: ๊ตฌํ˜„์€ ๋‹ค์Œ ์‚ฌํ•ญ๋“ค์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ ์ด์™ธ์— ๋“œ๋Ÿฌ๋‚˜๋Š” ๋™์ž‘์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์•„๋ž˜์— ์„ค๋ช… ๋œ ๊ฒƒ๊ณผ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํด๋กœ์ € ํƒ€์ž…์„ ์ •์˜ํ•ด๋„ ๋œ๋‹ค.

(2.1) โ€” the size and/or alignment of the closure type,
ํด๋กœ์ € ํƒ€์ž…์˜ ์‚ฌ์ด์ฆˆ๋‚˜ ํ• ๋‹น๋Ÿ‰

(2.2) โ€” whether the closure type is trivially copyable (Clause 12),
ํด๋กœ์ € ํƒ€์ž…์ด ๋ณต์‚ฌ ๊ฐ€๋Šฅํ•œ์ง€ ์•„๋‹Œ์ง€,

(2.3) โ€” whether the closure type is a standard-layout class Clause 12), or
ํด๋กœ์ €ํƒ€์ž…์ด ํ‘œ์ค€ ๋ ˆ์ด์•„์›ƒ ํด๋ž˜์Šค์ธ์ง€ ์•„๋‹Œ์ง€,

(2.4) โ€” whether the closure type is a POD class (Clause 12).
ํด๋กœ์ €ํƒ€์ž…์ด POD ํด๋ž˜์Šค์ธ์ง€ ์•„๋‹Œ์ง€.


An implementation shall not add members of rvalue reference type to the closure type.
๊ตฌํ˜„์€ ํด๋กœ์ € ํƒ€์ž…์— ์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ ํƒ€์ž…์˜ ๋ฉค๋ฒ„๋“ค์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

3 The closure type for a non-generic lambda-expression has a public inline function call operator (16.5.4)
: ๋น„-์ œ๋„ˆ๋ฆญ ๋žŒ๋‹ค์‹์˜ ํด๋กœ์ € ํƒ€์ž…์€ ๊ณต๊ฐœ๋œ ์ธ๋ผ์ธ ํ•จ์ˆ˜ ์—ฐ์‚ฐ์ž(ํ•จ์ˆ˜๊ฐ์ฒด)๋ฅผ ๊ฐ€์ง„๋‹ค.

whose parameters and return type are described by the lambda-expressionโ€™s parameter-declaration-clause and trailing-return-type respectively.ย 
: ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๋ฆฌํ„ดํƒ€์ž…์€ ๊ฐ๊ฐ ๋žŒ๋‹ค์‹์˜ ๋งค๊ฐœ ๋ณ€์ˆ˜ ์„ ์–ธ์ ˆ ๋ฐ ํ›„ํ–‰ ๋ฆฌํ„ดํƒ€์ž…(trailing-return-type)์— ์˜ํ•ด ์„ค๋ช…๋œ๋‹ค.

For a generic lambda, the closure type has a public inline function call operator member template (17.5.2) whose template parameter-list consists of one invented type template๏ฟพparameter for each occurrence of auto in the lambdaโ€™s parameter-declaration-clause, in order of appearance.
: ์ œ๋„ˆ๋ฆญ ๋žŒ๋‹ค์˜ ๊ฒฝ์šฐ, ํด๋กœ์ € ํƒ€์ž…์€ public ์ธ๋ผ์ธ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž ๋ฉค๋ฒ„ ํ…œํ”Œ๋ฆฟ(17.5.2)์„ ๊ฐ€์ง€๋ฉฐ, ๊ทธ ํ…œํ”Œ๋ฆฟ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฆฌ์ŠคํŠธ๋Š” ๋žŒ๋‹ค ํŒŒ๋ผ๋ฏธํ„ฐ ์„ ์–ธ ๋ถ€์—์„œ ๋‚˜ํƒ€๋‚œ ์ˆœ์„œ๋Œ€๋กœ, ๊ฐ ์ž๋™ ๋ฐœ์ƒ์— ๋Œ€ํ•œ ํ•˜๋‚˜์˜ ๊ธ‰์กฐ๋œ(invented) ํƒ€์ž… ํ…œํ”Œ๋ฆฟ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

The invented type template-parameter is a parameter pack if the corresponding parameter-declaration declares a function parameter pack (11.3.5).ย 
: ๊ธ‰์กฐ๋œ ํƒ€์ž… ํ…œํ”Œ๋ฆฟ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋งŒ์•ฝ ํ•ด๋‹น๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ์„ ์–ธ์ด ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํŒฉ์„ ์„ ์–ธํ•œ๋‹ค๋ฉด, ํ•˜๋‚˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํŒฉ์ด ๋œ๋‹ค.

The return type and function parameters of the function call operator template are derived from the lambda-expressionโ€™s trailing-return-type and parameter-declaration-clause by replacing each occurrence of auto in the decl-specifiers of the parameter-declaration-clause with the name of the corresponding invented template-parameter.ย 
: ํ•จ์ˆ˜ ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ์˜ ๋ฆฌํ„ดํƒ€์ž…๊ณผ ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋žŒ๋‹ค์‹์˜ trailing-return-type๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ ์–ธ์ ˆ๋กœ๋ถ€ํ„ฐ ์œ ๋„๋œ๋‹ค.
ํŒŒ๋ผ๋ฏธํ„ฐ ์„ ์–ธ์ ˆ์˜ decl ์ง€์ •์ž์—์„œ auto์˜ ๋ฐœ์ƒ์„ ๊ฐ๊ฐ ๊ธ‰์กฐ๋œ ํ…œํ”Œ๋ฆฟ ํŒŒ๋ผ๋ฏธํ„ฐ์— ํ•ด๋‹นํ•˜๋Š” ์ด๋ฆ„์œผ๋กœ ๊ต์ฒดํ•ด์„œ ๋ง์ด๋‹ค.



[Example:

auto glambda = [](auto a, auto&& b) { return a < b; };

bool b = glambda(3, 3.14); // OK

auto vglambda = [](auto printer)
{
ย ย ย  return [=](auto&& ... ts)
ย ย ย  {
ย ย ย  // OK: ts๋Š” ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํŒฉ์ด๋‹ค.

ย ย ย ย ย ย ย  printer(std::forward<decltype(ts)>(ts)...);

ย ย ย ย ย ย ย  return [=]() { printer(ts ...); };
ย ย ย  };
};

auto p = vglambda( [](auto v1, auto v2, auto v3)

{ std::cout << v1 << v2 << v3; } );

auto q = p(1, โ€™aโ€™, 3.14); // OK: 1a3.14 ์ถœ๋ ฅ

q(); // OK: 1a3.14 ์ถœ๋ ฅ.

โ€” end example ]



4 The function call operator or operator template is declared const (12.2.2) if and only if the lambda-expressionโ€™s parameter-declaration-clause is not followed by mutable.ย 
: ํ•จ์ˆ˜๊ฐ์ฒด๋‚˜ ์—ฐ์‚ฐ์žํ…œํ”Œ๋ฆฟ์€ ์˜ค์ง ๋žŒ๋‹ค์‹์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ ์–ธ์ ˆ์— mutable์ด ๋”ฐ๋ผ์˜ค์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋งŒ const๋กœ ์„ ์–ธ๋œ๋‹ค.


It is neither virtual nor declared volatile.
: virtual๋„ ์•„๋‹ˆ๊ณ  volatile๋„ ์„ ์–ธ๋˜์ง€๋„ ์•Š๋Š”๋‹ค.

Any noexcept-specifier specified on a lambda-expression applies to the corresponding function call operator or operator template.ย 
: ๋žŒ๋‹ค์‹์— ์ง€์ •๋œ ๋ชจ๋“  noexcept ์ง€์ •์ž๋Š” ํ•ด๋‹น๋˜๋Š” ํ•จ์ˆ˜ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž๋‚˜ ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ์— ์ ์šฉ๋œ๋‹ค.


An attribute-specifier-seq in a lambda-declarator appertains to the type of the corresponding function call operator or operator template.ย 
: ๋žŒ๋‹ค-์„ ์–ธ์ž์— ์žˆ๋Š” attribute ์ง€์ •์ž ์‹œํ€€์Šค๋Š” ํ•ด๋‹น๋˜๋Š” ํ•จ์ˆ˜ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž๋‚˜ ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ์˜ ํƒ€์ž…์— ์†ํ•œ๋‹ค.


The function call operator or any given operator template specialization is a constexpr function if either the corresponding lambda-expressionโ€™s parameter-declaration๏ฟพclause is followed by constexpr, or it satisfies the requirements for a constexpr function (10.1.5).ย 
: ํ•จ์ˆ˜ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž๋‚˜ ์–ด๋–ค ํŠน์ • ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ ํŠน์ˆ˜ํ™”๋Š” ๋žŒ๋‹ค์‹์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ ์–ธ์ ˆ์— constexpr์ด ๋”ฐ๋ผ์˜ค๊ฑฐ๋‚˜, constexpr ํ•จ์ˆ˜์˜ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋งŒ์กฑํ•  ๊ฒฝ์šฐ, constexpr ํ•จ์ˆ˜๊ฐ€ ๋œ๋‹ค.

[ Note: Names referenced in the lambda-declarator are looked up in the context in which the lambda-expression appears. โ€” end note ]ย 
: Note: ๋žŒ๋‹ค์‹ ์„ ์–ธ์ž์—๊ฒŒ ์ฐธ์กฐ๋œ ์ด๋ฆ„๋“ค์€ ๋žŒ๋‹ค์‹์ด ๋‚˜ํƒ€๋‚œ ์ปจํ…์ŠคํŠธ์—์„œ ๋ฃฉ์—…๋œ๋‹ค.


[Example:ย 

auto ID = [](auto a) { return a; };

static_assert(ID(3) == 3); // OK

struct NonLiteral
{
ย ย ย  NonLiteral(int n) : n(n) { }
ย ย ย  int n;
};

static_assert(ID(NonLiteral{3}).n == 3); // ill-formed

โ€” end example ]



5 [Example:

auto monoid = [](auto v)
{
ย ย ย  return [=] { return v; };
};

auto add = [](auto m1) constexpr
{
ย ย ย  auto ret = m1();
ย ย ย  return [=](auto m2) mutable
ย ย ย  {
ย ย ย ย ย ย ย  auto m1val = m1();
ย ย ย ย ย ย ย  auto plus = [=](auto m2val) mutable constexpr
ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย  return m1val += m2val;
ย ย ย ย ย ย ย  };
ย ย ย ย ย ย ย  ret = plus(m2());
ย ย ย ย ย ย ย  return monoid(ret);
ย ย ย  };
};

constexpr auto zero = monoid(0);

constexpr auto one = monoid(1);

static_assert(add(one)(zero)() == one());
// OK

// Since two below is not declared constexpr, an evaluation of its constexpr member function call operator
: ์•„๋ž˜ ๋‘ ๊ฐœ๋Š” constexpr๋กœ ์„ ์–ธ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋‚˜, constexpr ๋ฉค๋ฒ„ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž๋กœ ํ‰๊ฐ€.

// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture)
: ํ•ด๋‹น ์บก์ณ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์„œ๋ธŒ๊ฐ์ฒด ์ค‘ ํ•˜๋‚˜์—์„œ ์™ผ๊ฐ’์—์„œ ์˜ค๋ฅธ๊ฐ’์œผ๋กœ์˜ ๋ณ€ํ™˜์€ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†๋‹ค.

// in a constant expression.
: ์ƒ์ˆ˜ ํ‘œํ˜„์‹์—์„œ

auto two = monoid(2);

assert(two() == 2);
// OK, ์ƒ์ˆ˜ ํ‘œํ˜„์‹์ด ์•„๋‹ˆ๋‹ค.

static_assert(add(one)(one)() == two());
// ์ž˜๋ชป๋œ ํฌ๋งท: two()๋Š” ์ƒ์ˆ˜ ํ‘œํ˜„์‹์ด ์•„๋‹˜

static_assert(add(one)(one)() == monoid(2)()); // OK

โ€” end example ]



6 The closure type for a non-generic lambda-expression with no lambda-capture has a conversion function to pointer to function with C++ language linkage (10.5) having the same parameter and return types as the closure typeโ€™s function call operator.ย 
: ์บก์ณ๊ฐ€ ์—†๋Š” ๋น„-์ œ๋„ˆ๋ฆญ ๋žŒ๋‹ค ํ‘œํ˜„์‹์˜ ํด๋กœ์ € ํƒ€์ž…์€ ํด๋กœ์ € ํƒ€์ž…์˜ ํ•จ์ˆ˜ํ˜ธ์ถœ์—ฐ์‚ฐ์ž์™€ ๊ฐ™์€ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๋ฆฌํ„ดํƒ€์ž…์˜ C++์–ธ์–ด ์—ฐ๊ฒฐ(10.5) ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ, ๋ณ€ํ™˜(conversion) ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง„๋‹ค.


The conversion is to โ€œpointer to noexcept functionโ€ if the function call operator has a non-throwing exception specification.ย 
: ๊ทธ ํ•จ์ˆ˜ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž๊ฐ€ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€์ง€ ์•Š๋Š”๋‹ค๋Š” ์ง€์ •์ž๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค๋ฉด, ๊ทธ ๋ณ€ํ™˜์€ "noexcept ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ"๊ฐ€ ๋œ๋‹ค.


The value returned by this conversion function is the address of a function F that, when invoked, has the same effect as invoking the closure typeโ€™s function call operator.ย 
: ์ด ๋ณ€ํ™˜ ํ•จ์ˆ˜์— ์˜ํ•ด ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ’์€ ํ•จ์ˆ˜ F์˜ ์ฃผ์†Œ์ด๊ณ , ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ํด๋กœ์ €ํƒ€์ž…์˜ ํ•จ์ˆ˜ํ˜ธ์ถœ์—ฐ์‚ฐ์ž๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํšจ๊ณผ๋ฅผ ๋‚ธ๋‹ค.


F is a constexpr function if the function call operator is a constexpr function.
: ๊ทธ ํ•จ์ˆ˜ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž๊ฐ€ constexpr ํ•จ์ˆ˜๋ผ๋ฉด, F๋„ constexpr ํ•จ์ˆ˜๊ฐ€ ๋œ๋‹ค.

For a generic lambda with no lambda-capture, the closure type has a conversion function template to pointer to function.
: ์บก์ณ ์—†๋Š” ์ œ๋„ˆ๋ฆญ ๋žŒ๋‹ค์˜ ๊ฒฝ์šฐ, ๊ทธ ํด๋กœ์ €ํƒ€์ž…์€ ๊ทธ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ, ๋ณ€ํ™˜ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ์„ ๊ฐ€์ง„๋‹ค.


The conversion function template has the same invented template-parameter-list, and the pointer to function has the same parameter types, as the function call operator template.ย 
: ๋ณ€ํ™˜ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ์€ ๋™์ผํ•œ ๊ธ‰์กฐ๋œ-ํ…œํ”Œ๋ฆฟํŒŒ๋ผ๋ฏธํ„ฐ-๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€์ง„๋‹ค.
๊ทธ๋ฆฌ๊ณ  ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋Š” ๊ทธ ํ•จ์ˆ˜ํ˜ธ์ถœ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ๊ณผ ๊ฐ™์ด, ๋™์ผํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…์„ ๊ฐ€์ง„๋‹ค.


The return type of the pointer to function shall behave as if it were a decltype-specifier denoting the return type of the corresponding function call operator template specialization.
: ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ์˜ ๋ฆฌํ„ด ํƒ€์ž…์€, decltype ์ง€์ •์ž๊ฐ€ ํ•ด๋‹น๋˜๋Š” ํ•จ์ˆ˜ํ˜ธ์ถœ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ ํŠน์ˆ˜ํ™”์˜ ๋ฆฌํ„ดํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ํ–‰๋™ํ•œ๋‹ค.


7 [ Note: If the generic lambda has no trailing-return-type or the trailing-return-type contains a placeholder type, return type deduction of the corresponding function call operator template specialization has to be done.
: ์ œ๋„ˆ๋ฆญ ๋žŒ๋‹ค๊ฐ€ trailing-return-type์„ ๊ฐ–๊ณ ์žˆ์ง€ ์•Š๊ฑฐ๋‚˜, ๊ทธ trailing-return-type์ด placeholder ํƒ€์ž…์„ ํฌํ•จํ•œ๋‹ค๋ฉด, ํ•ด๋‹น๋˜๋Š” ํ•จ์ˆ˜ํ˜ธ์ถœ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ ํŠน์ˆ˜ํ™”์˜ ๋ฆฌํ„ดํƒ€์ž… ์—ฐ์—ญ์€ ์ˆ˜ํ–‰๋˜์–ด์•ผ๋งŒ ํ•œ๋‹ค.

The corresponding specialization is that instantiation of the function call operator template with the same template arguments as those deduced for the conversion function template.ย 
: ํ•ด๋‹น๋˜๋Š” ํŠน์ˆ˜ํ™”๋Š” ๋ณ€ํ™˜ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ์— ์ถ”๋ก ๋œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ํ…œํ”Œ๋ฆฟ ์—ฐ์‚ฐ์ž๋ฅผ ๊ฐ€์ง€๋Š” ํ•จ์ˆ˜ํ˜ธ์ถœ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ์˜ ์ธ์Šคํ„ดํŠธํ™”์ด๋‹ค.


Consider the following:
->์ด๋Ÿฐ๊ฑธ ๊ณ ๋ คํ•ด๋ณด์ž

auto glambda = [](auto a) { return a; };

int (*fp)(int) = glambda;

The behavior of the conversion function of glambda above is like that of the following conversion function:
->glambda์˜ ๋ณ€ํ™˜ํ•จ์ˆ˜๊ฐ€ ํ•˜๋Š” ํ–‰๋™์€ ์•„๋ž˜ ๋ณ€ํ™˜ํ•จ์ˆ˜๊ฐ€ ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

struct Closure {
ย ย ย  template auto operator()(T t) const
ย ย ย  { ... }

ย ย ย  template static auto lambda_call_operator_invoker(T a)
ย ย ย  {
ย ย ย  // forwards execution to operator()(a) and therefore has
ย ย ย  // the same return type deduced
ย ย ย  ...
ย ย ย  }

ย ย ย  template using fptr_t =ย ย ย  decltype(lambda_call_operator_invoker(declval())) (*)(T);

ย ย ย  template operator fptr_t() const
ย ย ย  {
ย ย ย ย ย ย ย  return &lambda_call_operator_invoker;
ย ย ย  }
};

โ€” end note ]



[Example:

void f1(int (*)(int)) { }

void f2(char (*)(int)) { }

void g(int (*)(int)) { } // #1

void g(char (*)(char)) { } // #2

void h(int (*)(int)) { } // #3

void h(char (*)(int)) { } // #4

auto glambda = [](auto a) { return a; };

f1(glambda); // OK

f2(glambda); // error: ID๋Š” ์ „ํ™˜ํ•  ์ˆ˜ ์—†๋‹ค.

g(glambda); // error: ๋ชจํ˜ธํ•จ

h(glambda); // OK: calls #3 since it is convertible from ID

int& (fpi)(int) = [](auto* a) -> auto& { return *a; }; // OK

โ€” end example ]



8 The value returned by any given specialization of this conversion function template is the address of a function F that, when invoked, has the same effect as invoking the generic lambdaโ€™s corresponding function call operator template specialization.ย 
: ์ด ๋ณ€ํ™˜ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ์˜ ์–ด๋–ค ํŠน์ˆ˜ํ™”์— ์˜ํ•ด ๋ฆฌํ„ด๋˜๋Š” ๊ฐ’์€ ํ•จ์ˆ˜ F์˜ ์ฃผ์†Œ์ด๋‹ค.
๊ทธ๋ฆฌ๊ณ  ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ๊ทธ ์ œ๋„ˆ๋ฆญ ๋žŒ๋‹ค์— ํ•ด๋‹นํ•˜๋Š” ํ•จ์ˆ˜ํ˜ธ์ถœ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ ํŠน์ˆ˜ํ™”๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ํšจ๊ณผ๋ฅผ ๋‚ธ๋‹ค.


F is a constexpr function if the corresponding specialization is a constexpr function.ย 
: ํ•ด๋‹นํ•˜๋Š” ํŠน์ˆ˜ํ™”๊ฐ€ constexpr ํ•จ์ˆ˜๋ผ๋ฉด F๋Š” constexpr ํ•จ์ˆ˜๊ฐ€ ๋œ๋‹ค.


[ Note: This will result in the implicit instantiation of the generic lambdaโ€™s body.
: ์ด๊ฑด ์ œ๋„ˆ๋ฆญ ๋žŒ๋‹ค ๋ชธ์ฒด์˜ ์•”์‹œ์ ์ธ ์ธ์Šคํ„ด์Šคํ™”๋ฅผ ์ดˆ๋ž˜ํ•œ๋‹ค.
The instantiated generic lambdaโ€™s return type and parameter types shall match the return type and parameter types of the pointer to function. โ€” end note ]ย 
: ์ธ์Šคํ„ด์Šคํ™”๋œ ์ œ๋„ˆ๋ฆญ ๋žŒ๋‹ค์˜ ๋ฆฌํ„ดํƒ€์ž…๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐํƒ€์ž…์€ ๊ทธ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ์˜ ๋ฆฌํ„ดํƒ€์ž…๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐํƒ€์ž…์— ๋งค์น˜๋œ๋‹ค.


[Example:

auto GL = [](auto a) { std::cout << a; return a; };

int (*GL_int)(int) = GL;
// OK: ๋ณ€ํ™˜ํ•จ์ˆ˜ํ…œํ”Œ๋ฆฟ์„ ํ†ตํ•จ.

GL_int(3);
// OK: GL(3)์™€ ๊ฐ™์Œ

โ€” end example ]



9 The conversion function or conversion function template is public, constexpr, non-virtual, non-explicit, const, and has a non-throwing exception specification (18.4).ย 
: ๋ณ€ํ™˜ํ•จ์ˆ˜๋‚˜ ๋ณ€ํ™˜ํ•จ์ˆ˜ ํ…œํ”Œ๋ฆฟ์€ public์ด๋ฉฐ, constexpr์ด๋ฉฐ, non-virtual์ด๋ฉฐ, ์•”์‹œ์ ์ด๋ฉฐ, constํ•˜๋ฉฐ, noexcept ์ง€์ •์ž๋ฅผ ๊ฐ€์ง„๋‹ค.


[ Example:

auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };

auto C = [](auto a) { return a; };

static_assert(Fwd(C,3) == 3); // OK

// No specialization of the function call operator template can be constexpr (due to the local static).
-> ํ•จ์ˆ˜ํ˜ธ์ถœ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ์˜ ํŠน์ˆ˜ํ™”๋Š” local static ๋•Œ๋ฌธ์— constexpr์ด ๋  ์ˆ˜ ์—†๋‹ค.

auto NC = [](auto a) { static int s; return a; };

static_assert(Fwd(NC,3) == 3); // ill-formed

โ€” end example ]


10 The lambda-expressionโ€™s compound-statement yields the function-body (11.4) of the function call operator, but for purposes of name lookup (6.4), determining the type and value of this (12.2.2.1) and transforming id๏ฟพexpressions referring to non-static class members into class member access expressions using (*this) (12.2.2), the compound-statement is considered in the context of the lambda-expression.ย 
: ๋žŒ๋‹ค์‹์˜ ๋ณตํ•ฉ๊ตฌ๋ฌธ์€ ๊ทธ ํ•จ์ˆ˜ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž์˜ ํ•จ์ˆ˜๋ชธ์ฒด๋ฅผ ๋‚ด์–ด์ค€๋‹ค.
ํ•˜์ง€๋งŒ ์ด๋ฆ„ ๋ฃฉ์—…์„ ๋ชฉ์ ์œผ๋กœ ํ•  ๊ฒฝ์šฐ, ์ด๊ฒƒ์˜ ํƒ€์ž…๊ณผ ๊ฐ’์„ ๊ฒฐ์ •ํ•˜๊ณ , ๋น„-์ •์  ํด๋ž˜์Šค ๋ฉค๋ฒ„๋ฅผ ์ฐธ์กฐํ•˜๋Š” id? ํ‘œํ˜„์‹์„ *this๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค ๋ฉค๋ฒ„ ์•ก์„ธ์Šค ํ‘œํ˜„์‹์œผ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๊ทธ ๋ณตํ•ฉ๊ตฌ๋ฌธ์€ ๊ทธ ๋žŒ๋‹ค์‹์˜ ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ๊ณ ๋ ค๋œ๋‹ค.


[Example:

struct S1
{
ย ย ย  int x, y;
ย ย ย  int operator()(int);

ย ย ย  void f()
ย ย ย  {
ย ย ย ย ย ย ย  [=]()->int
ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย  return operator()(this->x + y);
ย ย ย ย ย ย ย ย ย ย ย  // equivalent to S1::operator()(this->x + (this).y)
ย ย ย ย ย ย ย ย ย ย ย  // this has type S1

ย ย ย ย ย ย ย  };
ย ย ย  }
};

โ€” end example ]ย 



Further, a variable func is implicitly defined at the beginning of the compound-statement of the lambda-expression, with semantics as described in 11.4.1.
: ๋” ๋‚˜์•„๊ฐ€์„œ ๋ณ€์ˆ˜ __func__๋Š” ํ•จ์‹œ์ ์œผ๋กœ ๋žŒ๋‹ค์‹์˜ ๋ณตํ•ฉ๊ตฌ๋ฌธ ์‹œ์ž‘๋ถ€๋ถ„์—์„œ ์ •์˜๋˜์—ˆ๋‹ค.
11.4.1์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ์˜๋ฏธ๋กœ.


11 The closure type associated with a lambda-expression has no default constructor and a deleted copy assignment operator.ย 
: ๋žŒ๋‹ค์‹๊ณผ ๊ด€๋ จ๋œ ํด๋กœ์ €ํƒ€์ž…์€ ๊ทธ ์–ด๋–ค ๋””ํดํŠธ์ƒ์„ฑ์ž๋‚˜ ์‚ญ์ œ๋œ ๋ณต์‚ฌํ• ๋‹น์—ฐ์‚ฐ์ž๋„ ๊ฐ–๊ณ  ์žˆ์ง€ ์•Š๋‹ค.

It has a defaulted copy constructor and a defaulted move constructor (15.8).ย 
: ๋””ํดํŠธ ๋ณต์‚ฌ์ƒ์„ฑ์ž์™€ ๋””ํดํŠธ ์ด๋™์ƒ์„ฑ์ž๋ฅผ ๊ฐ€์ง„๋‹ค.

[ Note: These special member functions are implicitly defined as usual, and might therefore be defined as deleted. โ€” end note ]
: ์ด ํŠน์ˆ˜ํ•œ ๋ฉค๋ฒ„ํ•จ์ˆ˜๋Š” ์•”์‹œ์ ์œผ๋กœ ๊ทธ๋ƒฅ ์ •์˜๋˜๋ฏ€๋กœ, ์‚ญ์ œ๋œ ๊ฒƒ๊ณผ ๊ฐ™์ด ์ •์˜๋œ๋‹ค.


12 The closure type associated with a lambda-expression has an implicitly-declared destructor (15.4).
: ๋žŒ๋‹ค์‹๊ณผ ๊ด€๊ณ„๋œ ํด๋กœ์ €ํƒ€์ž…์€ ์•”์‹œ์ ์œผ๋กœ ์„ ์–ธ๋œ ์†Œ๋ฉธ์ž๋ฅผ ๊ฐ–๋Š”๋‹ค.


13 A member of a closure type shall not be explicitly instantiated (17.7.2), explicitly specialized (17.7.3), or named in a friend declaration (14.3).
: ํด๋กœ์ €ํƒ€์ž…์˜ ๋ฉค๋ฒ„๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์ธ์Šคํ„ด์Šคํ™”๋˜์ง€ ์•Š๊ณ , ๋ช…์‹œ์ ์œผ๋กœ ํŠน์ˆ˜ํ™”๋˜์ง€ ์•Š๊ณ , friend๋กœ ์„ ์–ธ๋˜์ง€ ๋ชปํ•œ๋‹ค.



8.1.5.2 Capturesย ->์บก์ณ


1 The body of a lambda-expression may refer to variables with automatic storage duration and the *this object (if any) of enclosing block scopes by capturing those entities, as described below.
: ๋žŒ๋‹ค์‹์˜ ๋ชธ์ฒด๋Š” ์ž๋™์ €์žฅ ๊ธฐ๊ฐ„์˜ ๋ณ€์ˆ˜์™€, ์•„๋ž˜์—์„œ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ด, ์—”ํ‹ฐํ‹ฐ๋“ค์„ ์บก์ณํ•ด์„œ ์—์›Œ์‹ผ ๋ธ”๋Ÿญ ์Šค์ฝ”ํ”„์˜ *this ๊ฐ์ฒด(์žˆ๋‹ค๋ฉด)๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜๋„ ์žˆ๋‹ค.


2 If a lambda-capture includes a capture-default that is &, no identifier in a simple-capture of that lambda-capture shall be preceded by &.ย 
: ์บก์ณ์—์„œ ์บก์ณ๋””ํดํŠธ &๋ฅผ ํฌํ•จํ•œ๋‹ค๋ฉด, ๊ทธ ์บก์ณ์˜ ์‹ฌํ”Œ์บก์ณ์—์„œ ๊ทธ๋ƒฅ ์‹๋ณ„์ž๋Š” &๋ณด๋‹ค ์•ž์— ์˜ฌ์ˆ˜ ์—†๋‹ค.

If a lambda-capture includes a capture-default that is =, each simple-capture of that lambda-capture shall be of the form โ€œ& identifierโ€ or โ€œ* thisโ€.ย 
: ๋งŒ์•ฝ ์บก์ณ๊ฐ€ ๋””ํดํŠธ์บก์ณ =๋ฅผ ํฌํ•จํ•œ๋‹ค๋ฉด, ๊ทธ ์บก์ณ์˜ ์‹ฌํ”Œ์บก์ณ๋Š” ๊ฐ๊ฐ &์‹๋ณ„์ž๋‚˜ *this์˜ ํ˜•์‹์„ ๊ฐ€์ ธ์•ผ๋งŒ ํ•œ๋‹ค.

[ Note: The form [&,this] is redundant but accepted for compatibility with ISO C++ 2014. โ€” end note ] Ignoring appearances in initializers of init-captures, an identifier or this shall not appear more than once in a lambda-capture.ย 
: [&,this] ๊ฐ™์€ ํ˜•์‹์€ ๋ณ„๋กœ ์“ธ๋ฐ๋Š” ์—†์ง€๋งŒ ISO C++2014์™€์˜ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด์„œ ํ—ˆ์šฉ๋œ๋‹ค.
์ดˆ๊ธฐํ™”์บก์ณ์˜ ์ด๋‹ˆ์…œ๋ผ์ด์ €์—์„œ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ๋ฌด์‹œํ•˜๋ฉด, ์‹๋ณ„์ž๋‚˜ this๋Š” ๋žŒ๋‹ค์บก์ณ์—์„œ ํ•œ๋ฒˆ ์ด์ƒ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์—†๋‹ค.


[Example:

struct S2 { void f(int i); };

void S2::f(int i)
{
ย ย ย  [&, i]{ }; // OK

ย ย ย  [&, &i]{ }; // error: i preceded by & when & is the default

ย ย ย  [=, *this]{ }; // OK

ย ย ย  [=, this]{ }; // error: this when = is the default

ย ย ย  [i, i]{ }; // error: i repeated

ย ย ย  [this, *this]{ }; // error: this appears twice
}

โ€” end example ]



3 A lambda-expression whose smallest enclosing scope is a block scope (6.3.3) is a local lambda expression;
any other lambda-expression shall not have a capture-default or simple-capture in its lambda-introducer.ย 
: ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ฐ”๊นฅ ์Šค์ฝ”ํ”„๊ฐ€ ๋ธ”๋Ÿญ ์Šค์ฝ”ํ”„์ธ ๋žŒ๋‹ค์‹์€ ๋กœ์ปฌ ๋žŒ๋‹ค์‹์ด๋‹ค.

The reaching scope of a local lambda expression is the set of enclosing scopes up to and including the innermost enclosing function and its parameters.ย 
: ๋กœ์ปฌ ๋žŒ๋‹ค์‹์˜ ๋„๋‹ฌ ๋ฒ”์œ„(์Šค์ฝ”ํ”„)๋Š” ๊ฐ€์žฅ ์•ˆ์ชฝ์—์„œ ๋‘˜๋Ÿฌ์‹ธ๋Š” ํ•จ์ˆ˜์™€ ๊ทธ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” ์ฃผ๋ณ€์Šค์ฝ”ํ”„์˜ ์ง‘ํ•ฉ์ด๋‹ค.

[ Note: This reaching scope includes any intervening lambda-expressions. โ€” end note ]
: ์ด ๋„๋‹ฌ๋ฒ”์œ„์—๋Š” ๋ผ์–ด์žˆ๋Š” ๋žŒ๋‹ค์‹๋“ค์ด ํฌํ•จ๋œ๋‹ค.


4 The identifier in a simple-capture is looked up using the usual rules for unqualified name lookup (6.4.1);
each such lookup shall find an entity.ย 
: ์‹ฌํ”Œ์บก์ณ์—์„œ์˜ ์‹๋ณ„์ž๋Š” ์ž๊ฒฉ์—†๋Š” ์ด๋ฆ„ ๋ฃฉ์—… ๋•Œ๋ฌธ์— ํ†ต์ƒ์ ์ธ ๊ทœ์น™์„ ์‚ฌ์šฉํ•ด์„œ ๋ฃฉ์—…์„ ํ•œ๋‹ค.


An entity that is designated by a simple-capture is said to be explicitly captured, and shall be this (when the simple-capture is โ€œthisโ€ or โ€œ thisโ€) or a variable with automatic storage duration declared in the reaching scope of the local lambda expression.
: ์‹ฌํ”Œ์บก์ณ์— ์˜ํ•ด ์ง€์ •๋œ ์—”ํ‹ฐํ‹ฐ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์บก์ณ๊ฐ€ ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  *this๋‚˜ ๊ทธ ๋กœ์ปฌ๋žŒ๋‹ค์‹์˜ ๋„๋‹ฌ๋ฒ”์œ„ ๋‚ด์—์„œ ์ž๋™์ €์žฅ๊ธฐ๊ฐ„์œผ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋„ ์“ธ ์ˆ˜๊ฐ€ ์žˆ๋‹ค.


5 If an identifier in a simple-capture appears as the declarator-id of a parameter of the lambda-declaratorโ€™s parameter-declaration-clause, the program is ill-formed.ย 
: ์‹ฌํ”Œ์บก์ณ์—์„œ์˜ ์‹๋ณ„์ž๊ฐ€ ๊ทธ ๋žŒ๋‹ค์„ ์–ธ์ž์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ์ด๋ฆ„์ด ๊ฐ™๋‹ค๋ฉด, ๊ทธ๊ฑด ์ž˜๋ชป๋œ ํ˜•์„์ด๋‹ค.


[ Example:

void f()
{
ใ…คint x = 0;

ใ…คauto g = [x](int x) { return 0; }
ใ…ค// error: parameter and simple-capture have the same name
}

โ€” end example ]



6 An init-capture behaves as if it declares and explicitly captures a variable of the form โ€œauto init-capture ;โ€
whose declarative region is the lambda-expressionโ€™s compound-statement, except that:
: ์ดˆ๊ธฐํ™”์บก์ณ๋Š” ๊ทธ๊ฒƒ์ด ์„ ์–ธ๋˜๊ณ  "์ž๋™ ์ดˆ๊ธฐํ™” ์บก์ณ" ํ˜•์‹์˜ ๋ณ€์ˆ˜๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์บก์ณํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ˆ˜ํ–‰๋œ๋‹ค. ์ด๊ฒŒ ์„ ์–ธ๋œ ๊ตฌ์—ญ์€ ๋žŒ๋‹ค์‹์˜ ๋ณตํ•ฉ๊ตฌ๋ฌธ์ด๋‹ค.
์ด๋Ÿฐ ๊ฒƒ๋“ค์€ ์ œ์™ธ๋œ๋‹ค:

(6.1) โ€” if the capture is by copy (see below), the non-static data member declared for the capture and the variable are treated as two different ways of referring to the same object, which has the lifetime of the non-static data member, and no additional copy and destruction is performed, and
: ์บก์ณ๊ฐ€ ๋ณต์‚ฌ๋œ๋‹ค๋ฉด, ๋น„-์ •์  ๋ฐ์ดํ„ฐ ๋ฉค๋ฒ„๊ฐ€ ์บก์ณ๋ฅผ ์œ„ํ•ด ์„ ์–ธ๋˜๊ณ , ๋ณ€์ˆ˜๊ฐ€ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์— ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ๋œ๋‹ค.
๊ทธ๋ž˜์„œ ๊ทธ๊ฒƒ์€ ๋น„-์ •์  ๋ฐ์ดํ„ฐ ๋ฉค๋ฒ„์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ฐ€์ง€๊ณ , ์ถ”๊ฐ€์ ์ธ ๋ณต์‚ฌ๋‚˜ ์†Œ๋ฉธ์€ ์ˆ˜ํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.
๊ทธ๋ฆฌ๊ณ ?

(6.2) โ€” if the capture is by reference, the variableโ€™s lifetime ends when the closure objectโ€™s lifetime ends.
: ๋งŒ์•ฝ ์บก์ณ๊ฐ€ ๋ ˆํผ๋Ÿฐ์Šค๋ผ๋ฉด ๊ทธ ๋ณ€์ˆ˜์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋Š” ํด๋กœ์ € ๊ฐ์ฒด์˜ ์ƒ๋ช…์ฃผ๊ธฐ ์ข…๋ฃŒ์‹œ์— ์ข…๋ฃŒ๋œ๋‹ค.

[ Note: This enables an init-capture like โ€œx = std::move(x)โ€; the second โ€œxโ€ must bind to a declaration in the surrounding context. โ€” end note ]ย 
: ์ด๊ฑด ์ดˆ๊ธฐํ™”์บก์ณ๋ฅผ โ€œx = std::move(x)โ€์ฒ˜๋Ÿผ ์“ฐ๋Š” ๊ฑธ ๊ฐ€๋Šฅ์ผ€ ํ•œ๋‹ค.
๋‘๋ฒˆ์งธ๋กœ "x"๋Š” ์ฃผ๋ณ€ ์ปจํ…์ŠคํŠธ์—์„œ ์„ ์–ธ๋œ ๊ฒƒ์„ ๋ฐ”์ธ๋”ฉํ•ด์•ผ๋งŒ ํ•œ๋‹ค.


[Example:

int x = 4;

auto y = [&r = x, x = x+1]()->int
{
ย ย ย  r += 2;
ย ย ย  return x+2;
}(); // Updates ::x to 6, and initializes y to 7.

auto z = [a = 42](int a) { return 1; }
// error: parameter and local variable have the same name

โ€” end example ]


7 A lambda-expression with an associated capture-default that does not explicitly capture *this or a variable with automatic storage duration (this excludes any id-expression that has been found to refer to an init๏ฟพcaptureโ€™s associated non-static data member), is said to implicitly capture the entity (i.e., *this or a variable)
: ์บก์ณ๋””ํดํŠธ์™€ ๊ด€๊ณ„๋œ ๋žŒ๋‹ค์‹์€ ๋ช…์‹œ์ ์œผ๋กœ *this๋‚˜ ์ž๋™์ €์žฅ๊ธฐ๊ฐ„ ๋ณ€์ˆ˜๋ฅผ ์บก์ณํ•˜์ง€ ์•Š๋Š”๋‹ค.
(์ด๊ฑด ์ดˆ๊ธฐํ™”์บก์ณ์™€ ๊ด€๊ณ„๋œ ๋น„-์ •์  ๋ฐ์ดํ„ฐ ๋ฉค๋ฒ„๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์—์„œ ๋ฐœ๊ฒฌ๋œ ๋ชจ๋“ ย  id ํ‘œํ˜„์‹์„ ์ œ์™ธํ•œ๋‹ค.)
๊ทธ๋ฆฌ๊ณ  ์•”์‹œ์ ์œผ๋กœ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์บก์ณํ•œ๋‹ค.
(*this๋‚˜ ๋ณ€์ˆ˜)


if the compound-statement:
: ๋ณตํ•ฉ๊ตฌ๋ฌธ์ด๋ผ๋ฉด ->

(7.1) โ€” odr-uses (6.2) the entity (in the case of a variable),

(7.2) โ€” odr-uses (6.2) this (in the case of the object designated by *this), or

(7.3) โ€” names the entity in a potentially-evaluated expression (6.2) where the enclosing full-expression depends on a generic lambda parameter declared within the reaching scope of the lambda-expression.
: ์ž ์žฌ์ ์œผ๋กœ ํ‰๊ฐ€๋˜๋Š” ํ‘œํ˜„์‹(6.2)์—์„œ ์—”ํ‹ฐํ‹ฐ์˜ ์ด๋ฆ„์„ ๋ช…๋ช…ํ•œ๋‹ค.
์—ฌ๊ธฐ์—์„œ ๋‘˜๋Ÿฌ์‹ผ ์ „์ฒด ํ‘œํ˜„์‹์€ ๋žŒ๋‹ค์‹์˜ ๋„๋‹ฌ ๋ฒ”์œ„ ๋‚ด์— ์„ ์–ธ๋œ ์ œ๋„ˆ๋ฆญ๋žŒ๋‹ค ํŒŒ๋ผ๋ฏธํ„ฐ์— ์˜์กด์ ์˜๋‹ค.


[Example:

void f(int, const int (&)[2] = {}) { } // #1

void f(const int&, const int (&)[1]) { } // #2

void test()
{
ย ย ย  const int x = 17;

ย ย ย  auto g = [](auto a)
ย ย ย  {
ย ย ย ย ย ย ย  f(x); // OK: calls #1, does not capture x
ย ย ย  };

ย ย ย  auto g2 = [=](auto a)
ย ย ย  {
ย ย ย ย ย ย ย  int selector[sizeof(a) == 1 ? 1 : 2]{};

ย ย ย ย ย ย ย  f(x, selector); // OK: is a dependent expression, so captures x
ย ย ย  };
}

โ€” end example ]ย 


All such implicitly captured entities shall be declared within the reaching scope of the lambda expression.ย 
: ์•”์‹œ์ ์ด๋กœ ์บก์ณ๋œ ์—”ํ‹ฐํ‹ฐ๋“ค์€ ์ „๋ถ€ ๋žŒ๋‹ค์‹์˜ ๋„๋‹ฌ๋ฒ”์œ„ ๋‚ด์—์„œ๋งŒ ์„ ์–ธ๋œ๋‹ค.


[ Note: The implicit capture of an entity by a nested lambda-expression can cause its implicit capture by the containing lambda-expression (see below). Implicit odr-uses of this can result in implicit capture. โ€” end note ]
: ์ค‘์ฒฉ๋œ ๋žŒ๋‹ค์‹์— ์˜ํ•œ ์—”ํ‹ฐํ‹ฐ์˜ ์•”์‹œ์  ์บก์ณ๋Š” ๋žŒ๋‹ค์‹์„ ํฌํ•จํ•ด์„œ ์•”์‹œ์ ์œผ๋กœ ์บก์ณํ•  ์ˆ˜ ์žˆ๋‹ค.
: ์ค‘์ฒฉ๋œ ๋žŒ๋‹ค์‹์—์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์•”์‹œ์ ์œผ๋กœ ์บก์ฒ˜ํ•˜๋ฉด ํฌํ•จ๋œ ๋žŒ๋‹ค์‹(์•„๋ž˜ ์ฐธ์กฐ)์— ์˜ํ•œ ์•”์‹œ ์  ์บก์ฒ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๊ฒƒ์„ ์•”์‹œ์ ์œผ๋กœ odr-usesํ•˜๋ฉด ์•”์‹œ์  ์บก์ฒ˜๊ฐ€ ์ดˆ๋ž˜๋  ์ˆ˜ ์žˆ๋‹ค.


8 An entity is captured if it is captured explicitly or implicitly.ย 
: ๊ทธ๊ฒŒ ๋ช…์‹œ์ ์ด๋“ , ์•”์‹œ์ ์ด๋“ , ์บก์ณ๊ฐ€ ๋œ๋‹ค๋ฉด, ์—”ํ‹ฐํ‹ฐ๋Š” ์บก์ณ๋œ๋‹ค.

An entity captured by a lambda-expression is odr-used (6.2) in the scope containing the lambda-expression.ย 
: ๋žŒ๋‹ค์‹์—๊ฒŒ ์บก์ณ๋œ ์—”ํ‹ฐํ‹ฐ๋Š” ๋žŒ๋‹ค์‹์„ ํฌํ•จํ•˜๋Š” ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ odr-used๋œ๋‹ค.

If *this is captured by a local lambda expression, its nearest enclosing function shall be a non-static member function.ย 
: *this๊ฐ€ ๋กœ์ปฌ๋žŒ๋‹ค์‹์—๊ฒŒ ์บก์ณ๋œ๋‹ค๋ฉด, ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ฃผ๋ณ€ ํ•จ์ˆ˜๋Š” ๋น„-์ •์  ๋ฉค๋ฒ„ํ•จ์ˆ˜๋‹ค.

If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses (6.2) this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression.
: ๋žŒ๋‹ค์‹์ด๋‚˜ ์ œ๋„ˆ๋ฆญ๋žŒ๋‹ค์˜ ํ•จ์ˆ˜ํ˜ธ์ถœ์—ฐ์‚ฐ์ž ํ…œํ”Œ๋ฆฟ์˜ ์ธ์Šคํ„ด์Šคํ™”๋Š” this๋‚˜ ๋„๋‹ฌ๋ฒ”์œ„์—์„œ ์ž๋™์ €์žฅ๊ธฐ๊ฐ„์œผ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋ฅผ odr-usesํ•œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๊ทธ ์—”ํ‹ฐํ‹ฐ๋Š” ๋žŒ๋‹ค์‹์—๊ฒŒ ์บก์ณ๋  ๊ฒƒ์ด๋‹ค.

If a lambda-expression captures an entity and that entity is not defined or captured in the immediately enclosing lambda expression or function, the program is ill-formed.ย 
: ๋žŒ๋‹ค์‹์ด ์—”ํ‹ฐํ‹ฐ๋ฅผ ์บก์ณํ–ˆ๋Š”๋ฐ, ๊ทธ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์ •์˜๋˜์ง€ ์•Š์•˜๊ฑฐ๋‚˜ ์ฃผ๋ณ€ ๋žŒ๋‹ค์‹์ด๋‚˜ ํ•จ์ˆ˜ ๋‚ด์—์„œ ๋ฐ”๋กœ ์บก์ณ๋œ๋‹ค๋ฉด, ๊ทธ๊ฑด ์ž˜๋ชป๋œ ํ˜•์‹์ด๋‹ค.

[ Example:

void f1(int i)
{
ย ย ย  int const N = 20;

ย ย ย  auto m1 = [=]
ย ย ย  {
ย ย ย ย ย ย ย  int const M = 30;

ย ย ย ย ย ย ย  auto m2 = [i]
ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย  int x[N][M];
ย ย ย ย ย ย ย ย ย ย ย  // OK: N and M are not odr-used

ย ย ย ย ย ย ย ย ย ย ย  x[0][0] = i;
ย ย ย ย ย ย ย ย ย ย ย  // OK: i is explicitly captured by m2 and implicitly captured by m1
ย ย ย ย ย ย ย  };
ย ย ย  };

ใ…คstruct s1
ย ย ย  {
ย ย ย ย ย ย ย  int f;

ย ย ย ย ย ย ย  void work(int n)
ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย  int m = n*n;

ย ย ย ย ย ย ย ย ย ย ย  int j = 40;

ย ย ย ย ย ย ย ย ย ย ย  auto m3 = [this,m]
ย ย ย ย ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  auto m4 = [&,j]
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  {ย ย ย ย 
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  // error: j not captured by m3

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  int x = n;
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  // error: n implicitly captured by m4 but not captured by m3

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  x += m;
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  // OK: m implicitly captured by m4 and explicitly captured by m3

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  x += i;
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  // error: i is outside of the reaching scope

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  x += f;
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  // OK: this captured implicitly by m4 and explicitly by m3

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  };
ย ย ย ย ย ย ย ย ย ย ย  };
ย ย ย ย ย ย ย  }
ย ย ย  };
}

struct s2
{
ย ย ย  double ohseven = .007;

ย ย ย  auto f()
ย ย ย  {
ย ย ย ย ย ย ย  return [this]
ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย  return [*this]
ย ย ย ย ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  return ohseven; // OK

ย ย ย ย ย ย ย ย ย ย ย  }
ย ย ย ย ย ย ย ย  }();
ย ย ย  }

ย ย ย  auto g()
ย ย ย  {
ย ย ย ย ย ย ย  return []
ย ย ย ย ย ย ย  {
ย ย ย ย ย ย ย ย ย ย ย  return [*this] { }; // error: *this not captured by outer lambda-expression
ย ย ย ย ย ย ย  }();
ย ย ย  }
};

โ€” end example ]


9 A lambda-expression appearing in a default argument shall not implicitly or explicitly capture any entity.
: ๋””ํดํŠธ์ธ์ž์—์„œ ๋‚˜ํƒ€๋‚˜๋Š” ๋žŒ๋‹ค์‹์€ ์•”์‹œ์ ์œผ๋กœ๋“ , ๋ช…์‹œ์ ์œผ๋กœ๋“ , ๊ทธ ์–ด๋–ค ์—”ํ‹ฐํ‹ฐ๋„ ์บก์ณํ•  ์ˆ˜ ์—†๋‹ค.


[Example:

void f2()
{
ย ย ย  int i = 1;

ย ย ย  void g1(int = ([i]{ return i; })()); // ill-formed

ย ย ย  void g2(int = ([i]{ return 0; })()); // ill-formed

ย ย ย  void g3(int = ([=]{ return i; })()); // ill-formed

ใ…คvoid g4(int = ([=]{ return 0; })()); // OK

ย ย ย  void g5(int = ([]{ return sizeof i; })()); // OK
}

โ€” end example ]


10 An entity is captured by copy if
: ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋ณต์‚ฌ๋กœ ์บก์ณ๋˜๋Š” ๊ฒฝ์šฐ:

(10.1) โ€” it is implicitly captured, the capture-default is =, and the captured entity is not *this, or
: ์•”์‹œ์ ์œผ๋กœ ์บก์ฒด๋˜๊ณ , ์บก์ณ๋””ํดํŠธ๊ฐ€ =์ด๊ณ  ์บก์ณ๋œ ์—”ํ‹ฐํ‹ฐ๊ฐ€ *this๊ฐ€ ์•„๋‹ˆ๊ฑฐ๋‚˜

(10.2) โ€” it is explicitly captured with a capture that is not of the form this, & identifier, or & identifier initializer.
&์‹๋ณ„์ž๋‚˜ &์‹๋ณ„์ž ์ด๋‹ˆ์…œ๋ผ์ด์ €, this๊ฐ€ ์•„๋‹Œ ํ˜•์‹์˜ ์บก์ณ๋กœ ๋ช…์‹œ์ ์œผ๋กœ ์บก์ณ๋  ๋•Œ,


For each entity captured by copy, an unnamed non-static data member is declared in the closure type.ย 
: ๋ณต์‚ฌ๋กœ ์บก์ณ๋œ ๊ฐ๊ฐ์˜ ์—”ํ‹ฐํ‹ฐ๋Š” ํด๋กœ์ €ํƒ€์ž… ๋‚ด์— ์„ ์–ธ๋œ ์ด๋ฆ„์—†๋Š” ๋น„-์ •์  ๋ฐ์ดํ„ฐ ๋ฉค๋ฒ„์ด๋‹ค.

The declaration order of these members is unspecified.ย 
: ์ด ๋ฉค๋ฒ„๋“ค์˜ ์„ ์–ธ ์ˆœ์„œ๋Š” ๋ช…์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค.

The type of such a data member is the referenced type if the entity is a reference to an object, an lvalue reference to the referenced function type if the entity is a reference to a function, or the type of the corresponding captured entity otherwise.ย 
: ๊ทธ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•œ๋‹ค๋ฉด ๋ฐ์ดํ„ฐ๋ฉค๋ฒ„์˜ ํƒ€์ž…์€ ์ฐธ์กฐ๋œ ํƒ€์ž…์ด๋ฉฐ,
๋งŒ์•ฝ ๊ทธ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ํ•จ์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๊ฑฐ๋‚˜ ํ•ด๋‹นํ•˜๋Š” ์บก์ณ๋œ ์—”ํ‹ฐํ‹ฐ์˜ ํƒ€์ž…์ด๋ผ๋ฉด, ์ฐธ์กฐ๋œ ํ•จ์ˆ˜ํƒ€์ž…์˜ ์™ผ๊ฐ’์ฐธ์กฐ๋‹ค.

A member of an anonymous union shall not be captured by copy.
: ์ต๋ช… ๊ณต์šฉ์ฒด์˜ ๋ฉค๋ฒ„๋Š” ๋ณต์‚ฌ๋กœ ์บก์ณ๋  ์ˆ˜ ์—†๋‹ค.


11 Every id-expression within the compound-statement of a lambda-expression that is an odr-use (6.2) of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type.ย 
: ๋ณต์‚ฌ๋กœ ์บก์ณ๋œ ์—”ํ‹ฐํ‹ฐ๊ฐ€ odr-use์ธ ๋žŒ๋‹ค์‹ ๋ณตํ•ฉ ๊ตฌ๋ฌธ ๋‚ด์˜ ๋ชจ๋“  idํ‘œํ˜„์‹์€ ํ•ด๋‹นํ•˜๋Š” ํด๋กœ์ €ํƒ€์ž…์˜ ์ด๋ฆ„์—†๋Š” ๋ฐ์ดํ„ฐ๋ฉค๋ฒ„๋กœ์˜ ์ ‘๊ทผ์œผ๋กœ ๋ณ€ํ™˜๋œ๋‹ค.


[ Note: An id-expression that is not an odr-use refers to the original entity, never to a member of the closure type. Furthermore, such an id-expression does not cause the implicit capture of the entity. โ€” end note ]ย 
: odr-use๊ฐ€ ์•„๋‹Œ idํ‘œํ˜„์‹์€ ์›๋ž˜ ์—”ํ‹ฐํ‹ฐ์˜ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€, ํด๋กœ์ €ํƒ€์ž…์˜ ๋ฉค๋ฒ„๋ฅผ ์ฐธ์กฐํ•˜์ง€ ์•Š๋Š”๋‹ค.
๊ฒŒ๋‹ค๊ฐ€ idํ‘œํ˜„์‹์€ ์—”ํ‹ฐํ‹ฐ์˜ ์•”์‹œ์  ์บก์ณ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค.


If *this is captured by copy, each odr-use of this is transformed into a pointer to the corresponding unnamed data member of the closure type, cast (8.4) to the type of this.ย 
*this๊ฐ€ ๋ณต์‚ฌ๋กœ ์บก์ณ๋œ๋‹ค๋ฉด, this์˜ odr-use๋Š” ๊ฐ๊ฐ ํ•ด๋‹นํ•˜๋Š” ํด๋กœ์ €ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฉค๋ฒ„์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋กœ ๋ณ€ํ™˜์ด ๋˜๋ฉฐ, this์˜ ํƒ€์ž…์œผ๋กœ ์บ์ŠคํŒ…๋œ๋‹ค.

[ Note: The cast ensures that the transformed expression is a prvalue. โ€” end note ]ย 
: ์ด ์บ์ŠคํŒ…์€ ๋ณ€ํ™˜๋œ ํ‘œํ˜„์‹์ด ์ˆœ์ˆ˜ ์˜ค๋ฅธ๊ฐ’์ž„์„ ๋ณด์žฅํ•œ๋‹ค.


An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference.ย 
: ์ฐธ์กฐ์— ์˜ํ•ด ์บก์ณ๋œ ์ฐธ์กฐ์˜ odr-use์ธ ๋žŒ๋‹ค์‹ ๋ณตํ•ฉ๊ตฌ๋ฌธ ๋‚ด idํ‘œํ˜„์‹์€ ์บก์ณ๋œ ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ๋ฐ”์ธ๋”ฉ๋œ ์—”ํ‹ฐํ‹ฐ๋งŒ ์ฐธ์กฐํ•˜๊ณ , ์บก์ณ๋œ ๋ ˆํผ๋Ÿฐ์Šค๋Š” ์ฐธ์กฐํ•˜์ง€ ์•Š๋Š”๋‹ค.

[ Note: The validity of such captures is determined by the lifetime of the object to which the reference refers, not by the lifetime of the reference itself. โ€” end note ]ย 
: ๊ทธ๋Ÿฐ ์บก์ณ์˜ ์œ ํšจ์„ฑ์€ ์ฐธ์กฐ๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๊ฐ์ฒด์˜ ์ƒ๋ช…์ฃผ๊ธฐ์— ์˜ํ•ด ๊ฒฐ์ •๋˜์ง€, ์ฐธ์กฐ ๊ทธ ์ž์ฒด์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋กœ ๊ฒฐ์ •๋˜์ง€๋Š” ์•Š๋Š”๋‹ค.


[Example:

void f(const int*);

void g()
{
ย ย ย  const int N = 10;

ย ย ย  [=]
ย ย ย  {
ย ย ย ย ย ย ย  int arr[N];
ย ย ย ย ย ย ย  // OK: not an odr-use, refers to automatic variable
ย ย ย ย ย ย ย  // odr-use๊ฐ€ ์•„๋‹˜, ์ž๋™๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•จ.

ย ย ย ย ย ย ย  f(&N); // OK: causes N to be captured; &N points to

ย ย ย ย ย ย ย  // the corresponding member of the closure type
ย ย ย  };
}

auto h(int &r)
{
ย ย ย  return [&]
ย ย ย  {
ย ย ย ย ย ย ย  ++r;
ย ย ย ย ย ย ย  // Valid after h returns if the lifetime of the

ย ย ย ย ย ย ย  // object to which r is bound has not ended
ย ย ย  };
}

โ€” end example ]


12 An entity is captured by reference if it is implicitly or explicitly captured but not captured by copy.ย 
: ์•”์‹œ์ ์ด๋“  ๋ช…์‹œ์ ์ด๋“  ์บก์ณ๋งŒ ๋œ๋‹ค๋ฉด, ์—”ํ‹ฐํ‹ฐ๋Š” ์ฐธ์กฐ๋กœ ์บก์ณ๊ฐ€ ๋˜์ง€๋งŒ, ๋ณต์‚ฌ๋กœ ์บก์ณ๋˜์ง€๋Š” ์•Š๋Š”๋‹ค.


It is unspecified whether additional unnamed non-static data members are declared in the closure type for entities captured by reference.ย 
: ์ถ”๊ฐ€์ ์œผ๋กœ ์ด๋ฆ„์—†๋Š” ๋น„-์ •์ ๋ฐ์ดํ„ฐ๋ฉค๋ฒ„๊ฐ€ ์ฐธ์กฐ๋กœ ์บก์ณ๋œ ์—”ํ‹ฐํ‹ฐ์— ๋Œ€ํ•œ ํด๋กœ์ €ํƒ€์ž… ๋‚ด์— ์„ ์–ธ๋˜๋Š”์ง€ ์•„๋‹Œ์ง€๋Š” ๋ช…์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค.

If declared, such non-static data members shall be of literal type.ย 
: ์„ ์–ธ๋œ๋‹ค๋ฉด, ๊ทธ๋Ÿฐ ๋น„-์ •์  ๋ฐ์ดํ„ฐ๋ฉค๋ฒ„๋Š” ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์ด ๋  ๊ฒƒ์ด๋‹ค.


[ Example:

// The inner closure type must be a literal type regardless of how reference captures are represented.
// ๋‚ด๋ถ€ ํด๋กœ์ € ํƒ€์ž…์€ ์ฐธ์กฐ์บก์ณ๊ฐ€ ํ‘œํ˜„๋˜๋Š”์ง€์™€ ์ƒ๊ด€์—†์ด ๋ฐ˜๋“œ์‹œ ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์ด ๋œ๋‹ค.

static_assert([](int n)
{ return [&n] { return ++n; }(); }(3) == 4);

โ€” end example ]


A bit-field or a member of an anonymous union shall not be captured by reference.
: ๋น„ํŠธํ•„๋“œ๋‚˜ ์ต๋ช…๊ณต์šฉ์ฒด์˜ ๋ฉค๋ฒ„๋Š” ์ฐธ์กฐ๋กœ ์บก์ณ๋  ์ˆ˜ ์—†๋‹ค.


13 If a lambda-expression m2 captures an entity and that entity is captured by an immediately enclosing lambda-expression m1, then m2โ€™s capture is transformed as follows:
: ๋งŒ์•ฝ ๋žŒ๋‹ค์‹ m2๊ฐ€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์บก์ณํ•˜๊ณ , ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๊ณง์žฅ ์ฃผ๋ณ€ ๋žŒ๋‹ค์‹ m1์— ์˜ํ•ด ์บก์ณ๋œ๋‹ค๋ฉด, m2์˜ ์บก์ณ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€ํ™˜๋  ๊ฒƒ์ด๋‹ค.

(13.1) โ€” if m1 captures the entity by copy, m2 captures the corresponding non-static data member of m1โ€™s closure type;
: ๋งŒ์•ฝ m1์ด ๋ณต์‚ฌ๋กœ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์บก์ณํ•œ๋‹ค๋ฉด, m2๋Š” ํ•ด๋‹น๋˜๋Š” m1์˜ ํด๋กœ์ €ํƒ€์ž…์˜ ๋น„-์ •์  ๋ฐ์ดํ„ฐ๋ฉค๋ฒ„๋ฅผ ์บก์ณํ•œ๋‹ค.

(13.2) โ€” if m1 captures the entity by reference, m2 captures the same entity captured by m1.
: m1์ด ์ฐธ์กฐ๋กœ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์บก์ณํ•œ๋‹ค๋ฉด m2๋Š” m1๊ฐ€ ์บก์ณํ•œ ๋™์ผ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์บก์ณํ•œ๋‹ค.

[Example: The nested lambda expressions and invocations below will output 123234.
: ์ค‘์ฒฉ ๋žŒ๋‹ค์‹๊ณผ ์•„๋ž˜์˜ ํ˜ธ์ถœ๋“ค์€ 123234๋ฅผ ์ถœ๋ ฅํ•  ๊ฒƒ์ด๋‹ค.

int a = 1, b = 1, c = 1;

auto m1 = [a, &b, &c]() mutable
{

ย ย ย  auto m2 = [a, b, &c]() mutable
ย ย ย  {
ย ย ย ย ย ย ย  std::cout << a << b << c;

ย ย ย ย ย ย ย  a = 4; b = 4; c = 4;
ย ย ย  };

ย ย ย  a = 3; b = 3; c = 3;

ย ย ย  m2();
};

a = 2; b = 2; c = 2;

m1();

std::cout << a << b << c;

โ€” end example ]



14 Every occurrence of decltype((x)) where x is a possibly parenthesized id-expression that names an entity of automatic storage duration is treated as if x were transformed into an access to a corresponding data member of the closure type that would have been declared if x were an odr-use of the denoted entity.ย 
: decltype((x))์˜ ๋ชจ๋“  ๊ฒฐ๊ณผ๋Š”
: decltype ((x))์—์„œ x๋Š” ์ž๋™์ €์žฅ๊ธฐ๊ฐ„์˜ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋ช…๋ช…ํ•˜๋Š” ๊ด„ํ˜ธ๋กœ ๋ฌถ์ธ idํ‘œํ˜„์‹์ธ๋ฐ,
x๊ฐ€ ํ‘œ์‹œ๋œ ์—”ํ‹ฐํ‹ฐ์˜ odr-use๋ผ๋ฉด,
x๊ฐ€ ์„ ์–ธ๋œ ํด๋กœ์ €ํƒ€์ž…์˜ ํ•ด๋‹น๋˜๋Š” ๋ฐ์ดํ„ฐ ๋ฉค๋ฒ„์— ๋Œ€ํ•œ ์ ‘๊ทผ์œผ๋กœ ๋ณ€ํ™˜๋œ ๊ฒƒ์ฒ˜๋Ÿผ ์ทจ๊ธ‰๋œ๋‹ค.


[ Example:

void f3()
{
ย ย ย  float x, &r = x;

ย ย ย  [=]
ย ย ย  {
ย ย ย ย ย ย ย  // x and r are not captured (appearance in a decltype operand is not an odr-use)
ย ย ย ย ย ย ย  // x์™€ r์€ ์บก์ณ๋˜์ง€ ์•Š๋Š”๋‹ค. (decltype ํ”ผ์—ฐ์‚ฐ์ž์—์„œ ๋‚˜ํƒ€๋‚˜๋Š”๊ฑด odr-use๊ฐ€ ์•„๋‹ˆ๋‹ค.)

ย ย ย ย ย ย ย  decltype(x) y1; // y1 has type float

ย ย ย ย ย ย ย  decltype((x)) y2 = y1;
ย ย ย ย ย ย ย  // y2 has type float const& because this lambda is not mutable and x is an lvalue
ย ย ย ย ย ย ย  // y2๋Š” ์ด ๋žŒ๋‹ค๊ฐ€ mut๊ฐ€ ์•„๋‹ˆ๊ณ  x๋„ ์™ผ๊ฐ’์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— float const&ํƒ€์ž…์„ ๊ฐ€์ง„๋‹ค.

ย ย ย ย ย ย ย  decltype(r) r1 = y1;
ย ย ย ย ย ย ย  // r1 has type float& (transformation not considered)
ย ย ย ย ย ย ย  // r1์€ float&ํƒ€์ž…์„ ๊ฐ€์ง„๋‹ค. (๋ณ€ํ™˜์€ ๊ณ ๋ ค๋˜์ง€ ์•Š์Œ)

ย ย ย ย ย ย ย  decltype((r)) r2 = y2;
ย ย ย ย ย ย ย  // r2 has type float const&
ย ย ย ย ย ย ย  // r2๋Š” float const&ํƒ€์ž…์„ ๊ฐ€์ง„๋‹ค.
ย ย ย  };
}

โ€” end example ]


15 When the lambda-expression is evaluated, the entities that are captured by copy are used to direct-initialize each corresponding non-static data member of the resulting closure object, and the non-static data members corresponding to the init-captures are initialized as indicated by the corresponding initializer (which may be copy- or direct-initialization).ย 
: ๋žŒ๋‹ค์‹์ด ํ‰๊ฐ€๋  ๋•Œ, ๋ณต์‚ฌ๋กœ ์บก์ณ๋œ ์—”ํ‹ฐํ‹ฐ๋“ค์€ ๊ฒฐ๊ณผ๋กœ ๋‚˜์˜จ ํด๋กœ์ €๊ฐ์ฒด์˜ ๊ฐ์ž ํ•ด๋‹น๋˜๋Š” ๋น„-์ •์  ๋ฐ์ดํ„ฐํƒ€์ž…์œผ๋กœ ์ง์ ‘ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๊ฒƒ์— ์‚ฌ์šฉ๋œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ดˆ๊ธฐํ™”์บก์ณ์— ํ•ด๋‹น๋˜๋Š” ๋น„-์ •์  ๋ฐ์ดํ„ฐ๋ฉค๋ฒ„๋“ค์€ ํ•ด๋‹นํ•˜๋Š” ์ด๋‹ˆ์…œ๋ผ์ด์ €์— ์˜ํ•ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ดˆ๊ธฐํ™”๋œ๋‹ค.(๋ณต์‚ฌ๋‚˜ ์ง์ ‘์ดˆ๊ธฐํ™”์ผ ๊ฒƒ์ž„)


(For array members, the array elements are direct-initialized in increasing subscript order.)ย 
: ๋ฐฐ์—ด ๋ฉค๋ฒ„์˜ ๊ฒฝ์šฐ, ๋ฐฐ์—ด์š”์†Œ๋“ค์€ ์ฆ๊ฐ€ํ•˜๋Š” ์„œ๋ธŒ์Šคํฌ๋ฆฝํŠธ ์ˆœ์„œ๋กœ ์ง์ ‘์ดˆ๊ธฐํ™”๋œ๋‹ค.


These initializations are performed in the (unspecified) order in which the non-static data members are declared.ย 
: ์ด ์ดˆ๊ธฐํ™”๋Š” ๋น„-์ •์  ๋ฐ์ดํ„ฐ๋ฉค๋ฒ„๊ฐ€ ์„ ์–ธ๋œ ์ˆœ์„œ๋Œ€๋กœ ์ˆ˜ํ–‰๋œ๋‹ค.


[ Note: This ensures that the destructions will occur in the reverse order of the constructions. โ€” end note ]
: ์ด๊ฒƒ์€ ์†Œ๋ฉธ์ž‘์—…์ด ์ƒ์„ฑ์˜ ์—ญ์ˆœ์œผ๋กœ ๋ฐœ์ƒํ•  ๊ฒƒ์ž„์„ ๋ณด์žฅํ•œ๋‹ค.