Generic Lambda (หรือ Polymorphic Lambda) เป็นฟีเจอร์สำคัญของ C++14 ที่อนุญาตให้ Lambda Expression ใช้ auto ใน Parameter List ทำให้ Lambda หนึ่งเดียวสามารถรับ Argument หลาย Type ได้ (Template-like)
Syntax
// C++11: Parameter Type ต้องระบุชัดเจน
auto add_int = [](int x, int y) { return x + y; };
// C++14: Generic Lambda
auto add = [](auto x, auto y) { return x + y; };
// เทียบเท่า Template Function:
template <typename T, typename U>
auto add_template(T x, U y) { return x + y; }
ตัวอย่างการใช้งาน
#include <iostream>
#include <string>
#include <vector>
int main() {
// 1. Generic Binary Operation
auto add = [](auto a, auto b) { return a + b; };
std::cout << "int: " << add(5, 8) << '\n'; // 13
std::cout << "double: " << add(2.75, 5.639) << '\n'; // 8.389
std::cout << "string: " << add(std::string("Hello "), std::string("World")) << '\n'; // Hello World
std::cout << "vector: " << add(std::vector<int>{1,2}, std::vector<int>{3,4}).size() << '\n'; // 4 (concat)
// 2. Generic Lambda ใน STL Algorithms
std::vector<int> v = {1, 2, 3, 4, 5};
auto print = [](const auto& x) { std::cout << x << ' '; };
std::for_each(v.begin(), v.end(), print); // 1 2 3 4 5
// 3. Capture by Reference/Value กับ auto
int factor = 10;
auto scale = [factor](auto x) { return x * factor; }; // Capture by Value
std::cout << "Scale 5: " << scale(5) << '\n'; // 50
return 0;
}
Generic Lambda vs Template Function
| Feature | Generic Lambda | Template Function |
|---|---|---|
| Syntax | Concise, Inline | Verbose, Separate Declaration |
| Capture | ได้ (Local Variables) | ไม่ได้ (Global/Static Only) |
| Type Deduction | Auto (C++14) | Template Parameters |
| SFINAE/Constraints | C++20: Concepts / Requires | Full Support (Enable_if, Concepts) |
| Recursion | ต้องใช้ std::function หรือ Y-Combinator | Direct Recursion ได้ |
| Overloading | ไม่ได้โดยตรง | ได้ |
C++20: Template Syntax for Lambdas (Explicit Template Parameters)
// C++20: ระบุ Template Parameters ให้ชัดเจน
auto vec_add = []<typename T>(const std::vector<T>& a, const std::vector<T>& b) {
std::vector<T> result;
result.reserve(a.size() + b.size());
result.insert(result.end(), a.begin(), a.end());
result.insert(result.end(), b.begin(), b.end());
return result;
};
ข้อจำกัดและข้อระวัง
- Return Type Deduction: ใช้
autoReturn (C++14) - ต้องมี Single Return Statement หรือ Return Types ตรงกันทุก Path - Perfect Forwarding: Generic Lambda ไม่รองรับ Universal Reference (
auto&&) โดยตรงใน C++14 (C++20 รองรับ) - ADL (Argument-Dependent Lookup): Lambda ไม่มี Associated Namespace ใช้
using namespaceใน Body หากต้องการ
สรุป
Generic Lambda (C++14) ทำให้เขียน Callable Objects แบบ Polymorphic ได้สะดวก ใช้ร่วมกับ STL Algorithms ได้อย่างเป็นธรรมชาติ ลด Boilerplate ของ Template Functions แต่อยู่ภายใต้ข้อจำกัดบางประการ (Recursion, Overloading, Perfect Forwarding) ที่ C++20 ช่วยแก้ไขบางส่วน