람다 표현식의 변화

1. auto 매개변수 (C++14~)

  • C++14부터 람다 표현식에서 auto를 파라미터 타입으로 사용 가능
  • 컴파일러가 두 개의 템플릿 인자를 가진 함수를 만들어주기 때문
  auto add = [](auto a, auto b) { return a + b; };
  
  • 서로 다른 타입 허용, 제약하려면 template 사용
  auto add2 = []<typename T>(T a, T b) { return a + b; };
// add2<int>(1, 2.2); // 오류, T는 동일 타입이어야 함
  

2. 평가되지 않은 표현식에서의 람다 (C++20~)

  • C++20부터 람다 표현식을 다음 네 가지 문맥에서 사용할 수 있음 (평가되지 않은 표현식)

    1. sizeof
    2. decltype
    3. typeid
    4. noexcept

예시 (기존에는 불가)

  std::unique_ptr<int, decltype([](int* p) { delete p; })> up(new int);
  

3. 캡처 없는 람다: 복사/대입 지원 (C++20~)

  int main()
{
    int v1 = 10;
    auto f1 = [v1](int a, int b) {return a + b;};
                            // C++11 ~ C++17    C++20
    decltype(f1) f2;        // Error            Error
    decltype(f1) f3 = f1;   // OK               OK
    f3 = f1;                // Error            Error
/*
    auto f1 = [](int a, int b) {return a + b;};
 
                            // C++11 ~ C++17    C++ 20
    decltype(f1) f2;        // Error            OK
    decltype(f1) f3 = f1;   // OK               OK
    f3 = f1;                // Error            OK
*/
}
  
  • C++20부터 캡처가 없는 경우에는 디폴트 생성자와 대입 연산자 지원

4. 암묵적 this 캡처 제거 (C++20에서 deprecated)

  • 기존: [=] 캡처는 this를 암묵적으로 포함했음
  • 문제: this가 파괴된 뒤 접근하면 정의되지 않은 동작 발생

안전한 대안

  // [=] 에서 this를 명시적으로 분리
[=, this]    // 명시적 캡처 (복사)
[=, *this]   // 멤버 값 복사
  

예시 코드

  struct Sample {
    int value = 0;
    auto foo() {
        int n = 10;
        auto f = [=, *this](int a) { return a + n + value; };
        return f;
    }
};

std::function<int(int)> f;
void goo() {
    Sample s;
    f = s.foo();
    std::cout << f(10) << std::endl;
}

int main() {
    goo();
    std::cout << f(10) << std::endl;
}
  

5. Capture Parameter Pack (C++20~)

  • 가변 인자를 캡처 가능

값으로 캡처

  template<typename ... Args>
auto f1(Args&&... args) {
    return [...args = std::forward<Args>(args)]() {
        (std::cout << ... << args);
    };
}
  

참조로 캡처

  template<typename ... Args>
auto f2(Args&&... args) {
    return [&...args = std::forward<Args>(args)]() {
        (std::cout << ... << args);
    };
}
  

요약

기능도입 버전설명
auto 매개변수 람다C++14타입 추론 가능한 일반화 람다
평가되지 않은 표현식에서 람다C++20decltype, sizeof 등에 람다 사용 가능
캡처 없는 람다 복사/대입 지원C++20디폴트 생성자 및 대입 연산자 사용 가능
this의 암묵적 캡처 제거 (deprecated)C++20명시적으로 [=, this] 또는 [=, *this] 필요
가변 인자 캡처C++20파라미터 팩을 값 또는 참조로 캡처 가능