C++20coreadvanced
Template Lambdas (C++20 Addition)
C++20 · The Big Four · Compiler flag: -std=c++20
Explanation
Lambdas with explicit template parameters for generic programming.
Real-World Scenario
Write a generic lambda for type-safe processing in a data pipeline.
Quick Snippet
snippet.cpp
auto lambda = []<typename T>(T x) { return x; };Full Example
template_lambdas.cpp
// CodeNebula - C++20 Example: Template Lambdas
// Compile: g++ -std=c++20 -Wall -Wextra -o example template_lambdas.cpp
// Demonstrates the C++20 template lambda syntax []<typename T>(T x) {}
// which gives lambdas explicit template parameters for precise type control.
#include <iostream>
#include <string>
#include <vector>
#include <type_traits>
#include <numeric>
int main()
{
// ------------------------------------------------------------------
// 1. Basic template lambda with single type parameter
// ------------------------------------------------------------------
std::cout << "=== Basic Template Lambda ===" << std::endl;
auto type_info = []<typename T>(T val) {
std::cout << " Value: " << val
<< " (size=" << sizeof(T) << ")" << std::endl;
};
type_info(42);
type_info(3.14f);
type_info(std::string("hello"));
// ------------------------------------------------------------------
// 2. Template lambda to enforce same-type arguments
// ------------------------------------------------------------------
std::cout << "\n=== Same-Type Enforcement ===" << std::endl;
auto add_same = []<typename T>(T a, T b) -> T {
return a + b;
};
std::cout << " int: " << add_same(3, 4) << std::endl;
std::cout << " double: " << add_same(1.5, 2.5) << std::endl;
std::cout << " string: " << add_same(std::string("ab"), std::string("cd"))
<< std::endl;
// add_same(1, 2.0); // Error: T deduced as both int and double
// ------------------------------------------------------------------
// 3. Template lambda with container deduction
// ------------------------------------------------------------------
std::cout << "\n=== Container Template Lambda ===" << std::endl;
auto sum_vec = []<typename T>(const std::vector<T>& v) -> T {
return std::accumulate(v.begin(), v.end(), T{});
};
std::cout << " sum(int): " << sum_vec(std::vector<int>{1, 2, 3, 4, 5})
<< std::endl;
std::cout << " sum(double): " << sum_vec(std::vector<double>{0.1, 0.2, 0.3})
<< std::endl;
// ------------------------------------------------------------------
// 4. Template lambda with non-type template parameter
// ------------------------------------------------------------------
std::cout << "\n=== Non-Type Template Parameter ===" << std::endl;
auto repeat = []<int N>(const std::string& s) {
std::string result;
for (int i = 0; i < N; ++i) result += s;
return result;
};
std::cout << " " << repeat.operator()<3>("Ha") << std::endl;
std::cout << " " << repeat.operator()<5>("*") << std::endl;
// ------------------------------------------------------------------
// 5. Template lambda with constexpr if
// ------------------------------------------------------------------
std::cout << "\n=== Template Lambda with if constexpr ===" << std::endl;
auto describe = []<typename T>(T val) {
if constexpr (std::is_integral_v<T>)
std::cout << " " << val << " is an integer" << std::endl;
else if constexpr (std::is_floating_point_v<T>)
std::cout << " " << val << " is a float" << std::endl;
else if constexpr (std::is_same_v<T, std::string>)
std::cout << " \"" << val << "\" is a string" << std::endl;
else
std::cout << " unknown type" << std::endl;
};
describe(42);
describe(2.71828);
describe(std::string("C++20"));
// ------------------------------------------------------------------
// 6. Multiple template parameters
// ------------------------------------------------------------------
std::cout << "\n=== Multiple Template Parameters ===" << std::endl;
auto convert = []<typename To, typename From>(From val) -> To {
return static_cast<To>(val);
};
int i = convert.operator()<int>(3.7);
double d = convert.operator()<double>(42);
std::cout << " 3.7 -> int: " << i << std::endl;
std::cout << " 42 -> double: " << d << std::endl;
// ------------------------------------------------------------------
// 7. Template lambda stored in auto variable
// ------------------------------------------------------------------
std::cout << "\n=== Reusable Template Lambda ===" << std::endl;
auto max_of = []<typename T>(T a, T b) { return (a > b) ? a : b; };
std::cout << " max(3, 7) = " << max_of(3, 7) << std::endl;
std::cout << " max(9.1, 2.5) = " << max_of(9.1, 2.5) << std::endl;
std::cout << " max(ab, cd) = "
<< max_of(std::string("ab"), std::string("cd")) << std::endl;
return 0;
}
/*
Expected output:
=== Basic Template Lambda ===
Value: 42 (size=4)
Value: 3.14 (size=4)
Value: hello (size=32)
=== Same-Type Enforcement ===
int: 7
double: 4
string: abcd
=== Container Template Lambda ===
sum(int): 15
sum(double): 0.6
=== Non-Type Template Parameter ===
HaHaHa
*****
=== Template Lambda with if constexpr ===
42 is an integer
2.71828 is a float
"C++20" is a string
=== Multiple Template Parameters ===
3.7 -> int: 3
42 -> double: 42
=== Reusable Template Lambda ===
max(3, 7) = 7
max(9.1, 2.5) = 9.1
max(ab, cd) = cd
*/
Run command
g++ -std=c++20 -Wall -Wextra -o example template_lambdas.cpp