Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Generic Lambda ใน C++14: ฟังก์ชันแนมที่รับ Type ใดๆ ได้

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

FeatureGeneric LambdaTemplate Function
SyntaxConcise, InlineVerbose, Separate Declaration
Captureได้ (Local Variables)ไม่ได้ (Global/Static Only)
Type DeductionAuto (C++14)Template Parameters
SFINAE/ConstraintsC++20: Concepts / RequiresFull Support (Enable_if, Concepts)
Recursionต้องใช้ std::function หรือ Y-CombinatorDirect 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: ใช้ auto Return (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 ช่วยแก้ไขบางส่วน