Skip to content

Last updated:2026-10-12

C++20 Lambda Expressions (Part 1)

C++20: Lambda Templates

C++14 supports generic lambda expressions, which lets a lambda accept parameters of any type, for example:

auto func = [](auto a, auto b) {
    return a + b;
};

which gets expanded into:

struct Func {
    template <typename T1, typename T2>
    auto operator()(T1 a, T2 b) const {
        return a + b;
    }
};

But it cannot produce the following kinds of expansions:

First: the same type

template <class T>
auto operator()(T t1, T t2) const;

Second: only std::array

template <class T, std::size_t N>
auto operator()(std::array<T, N> const &) const; 

Third: no deduction

template <class T>
auto operator()() const;

C++14 lambdas are nice, but C++20 lets us achieve these cases easily. C++20 allows lambda expressions to use template type parameters in their definition; here is the basic syntax:

[]<typename T>(){}

The following examples show its benefits.

1. Type Constraints

In an example like the one below, C++14 lets us write this code, but what gets passed in at the call site is not necessarily a vector, so the behavior deviates from what was intended and errors follow.

auto print = [](auto vec) {
  for (auto x : vec) {
    std::cout << x << std::endl;
  }
};

With C++20 and later, we can constrain the type:

auto print2 = []<typename T>(std::vector<T>& vec){
    //使用 std::vector<T> 执行操作
};

So here comes an interview question: in C++14, how would you constrain this to a vector safely?

2. Perfect Forwarding

In C++20 you can use perfect forwarding very easily, for example:

auto lambdaFunc = []<typename T>(T&& number) {
  processFunction(std::forward<T>(number));
};

So, what is the advantage over C++14? Or put another way: what does it take to implement perfect forwarding in C++14?

That's all for this section.

Comments