C++ Template Lambdas | Explicit Template Parameters in C++20 Lambdas
이 글의 핵심
Template lambdas add explicit template parameters to lambdas so you can enforce same-type parameters, use concepts, and write pack-friendly lambdas.
Introduction
C++20 template lambdas let you specify explicit template parameters on a lambda, giving you precise control and clean concept-based constraints.
1. Basics: auto vs template lambda
#include <iostream>
#include <typeinfo>
int main() {
// C++14: generic lambda
auto addAuto = {
return a + b;
};
// C++20: template lambda — both parameters share T
auto addTemplate = []<typename T>(T a, T b) {
return a + b;
};
std::cout << addTemplate(1, 2) << std::endl;
std::cout << addTemplate(1.5, 2.5) << std::endl;
// addTemplate(1, 2.5); // error: mismatched T
}
Printing with type info
auto print = []<typename T>(const T& value) {
std::cout << "type: " << typeid(T).name()
<< ", value: " << value << std::endl;
};
Ideas
- Explicit template parameters:
<typename T> - Enforce relationships between parameters
- Combine with concepts
2. Concepts
#include <concepts>
auto addInts = []<std::integral T>(T a, T b) {
return a + b;
};
auto addFloats = []<std::floating_point T>(T a, T b) {
return a + b;
};
Custom concepts
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
auto multiply = []<Numeric T>(T a, T b) {
return a * b;
};
3. Practical examples
Example 1: Multiple template parameters
#include <iostream>
int main() {
auto convert = []<typename From, typename To>(From value) {
return static_cast<To>(value);
};
auto result1 = convert.operator()<int, double>(10);
std::cout << result1 << std::endl;
auto result2 = convert.operator()<double, int>(3.14);
std::cout << result2 << std::endl;
auto toInt = []<typename From>(From value) {
return static_cast<int>(value);
};
std::cout << toInt(3.14) << std::endl;
}
Example 2: Containers
#include <iostream>
#include <vector>
#include <list>
#include <typeinfo>
int main() {
auto printContainer = []<typename Container>(const Container& c) {
using ValueType = typename Container::value_type;
std::cout << "container: " << typeid(Container).name() << std::endl;
std::cout << "value_type: " << typeid(ValueType).name() << std::endl;
std::cout << "elements: ";
for (const auto& item : c) {
std::cout << item << " ";
}
std::cout << std::endl;
};
std::vector<int> vec = {1, 2, 3, 4, 5};
printContainer(vec);
std::list<double> lst = {1.1, 2.2, 3.3};
printContainer(lst);
}
Example 3: Parameter packs
#include <iostream>
int main() {
auto sum = []<typename... Ts>(Ts... values) {
return (values + ...);
};
std::cout << sum(1, 2, 3) << std::endl;
std::cout << sum(1.5, 2.5, 3.5) << std::endl;
auto print = []<typename... Ts>(Ts... values) {
((std::cout << values << " "), ...);
std::cout << std::endl;
};
print(1, 2, 3);
print("Hello", 42, 3.14);
}
Example 4: Container transform
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
auto transform = []<typename Container, typename Func>(
const Container& input,
Func func
) {
using ValueType = typename Container::value_type;
Container output;
for (const auto& item : input) {
output.push_back(func(item));
}
return output;
};
std::vector<int> numbers = {1, 2, 3, 4, 5};
auto doubled = transform(numbers, [](int x) { return x * 2; });
for (int n : doubled) {
std::cout << n << " ";
}
std::cout << std::endl;
}
Summary
- Template lambdas are C++20.
- Concepts constrain
T(std::integral, custom concepts). - Packs work:
[]<typename... Ts>(Ts... values). - Explicit calls:
.operator()<int>(...).
auto vs template lambda
| Scenario | auto lambda | Template lambda |
|---|---|---|
| Independent parameter types | ✅ | ❌ (unless multiple Ts) |
Same T for multiple parameters | ❌ | ✅ |
Concepts on T | ❌ | ✅ |
| Explicit template args | ❌ | ✅ |
Related posts
- Generic lambda
constexprlambda- Concepts
Keywords
C++, template lambda, C++20, concepts, generic lambda.
See also
autotype deduction