C++20 에서 추가된 람다 표현식의 특징은 다음과 같습니다.

  1. 템플릿 사용 가능
  2. 평가 되지 않은 표현식 사용 가능
  3. 캡쳐 하지 않은 표현식에서 디폴트 생성자와 대입 연산자 사용 가능
  4. 암시적 this 캡쳐 deprecated
  5. parameter pack 캡쳐 가능

람다 표현식 템플릿

  • 기존에 람다 표현식 입력 인자를 auto로 할 경우 C++14 부터 자동으로 템플릿화 하여 여러 타입에 대응되는 표현식을 작성 할 수 있으나, 동일 타입에 대해서만 동작하게 만들 수 없었습니다.

  • C++20 방식 예제

    auto add = [](auto a, auto b) {return a+b;} // C++14 모든 타입 대응가능
    auto add = [](auto a, decltype(a) b) {return a+b;} // C++14 a와 b 타입 동일시 하지만, 원치 않은 동작 발생 가능
    auto add = []<typename T>(T a, T b) {return a+b;} // C++20 새로운 방식, 타입이 다를 경우 컴파일 오류 발생
    

평가 되지 않은 표현식

  • 런타임 시간에는 실행되지 않고, 컴파일 시간에만 사용 되는 표현식 sizoeof, decltype, typeid, nocept

  • C++17까지는 람다 표현식을 평가되지 않은 표현식으로 사용 할 수 없었음, But 20부터 가능해졌습니다.

    std::cout << sizeof( [](int a, int b) { return a+b; } ) << std::endl; // C++17 불가, C++20 허용
    
    // 활용 : 스마트 포인터 deleter의 인자로 람다를 넘겨 줄 수 있음 C++20
    std::unique_ptr<int, decltype( [](int* p) { delete p; })> pVal( new int );
    

람다 표현식과 디폴트 생성자

// 캡쳐 없는 케이스
int v = 10;
auto r1 = [](int a, int b) {return a + b};

						// ~C++17		C++20
decltype(r1) r2;		// 불가		   가능
decltype(r1) r3 = r1;	// 가능		   가능
r3 = r1;				// 불가		   가능

// 캡쳐 있는 케이스
int v = 10;
auto r1 = [v](int a, int b) {return a + b};

						// ~C++17		C++20
decltype(r1) r2;		// 불가		   !!불가!!
decltype(r1) r3 = r1;	// 가능		   가능
r3 = r1;				// 불가		   !!불가!!

암묵적 this 캡쳐 deprecated

  • 기존 람다 표현식 캡쳐시 [=] 할 경우 [=, this]와 같은 의미였습니다. [=]로 캡쳐시 표현식 안에서 지역변수와 모든 멤버 변수에 접근이 가능합니다. 하지만 객체 수명 주기로 인해 의도치 않은 버그를 만들어 낼 수 있습니다. (잡기 힘든 버그가 됨. 매우 위험)
  • C++ 20 부터는 [=] 로 캡쳐시 컴파일로 경고가 발생 합니다.( 암묵적 this 캡쳐 사용은 좋지 않은 방법이고. 명시적인 값복사 사용을 권장합니다. )

Parameter pack 캡쳐( C++17 이전에는 캡쳐 불가 )

// 값 캡쳐
template<typename ... Args> auto name(Args&&... args)
{
    return [...args = std::forward<args)](){ std::cout << ... << args); };
}

// 참조 캡쳐
template<typename ... Args> auto name(Args&&... args)
{
    return [&...args = std::forward<args)](){ std::cout << ... << args); };
}

더 많은 C++20 관련 정보