Ch15: Function Templates¶
TL;DR: Template Blueprints: Function Template ทำหน้าที่เป็นโครงร่าง (Blueprint) สำหรับสร้างโค้ด โดย Compiler จะแปลงเป็นโค้ดจริง (Instantiation) เฉพาะกับชนิดข้อมูลที่มีการเรียกใช้งานตอน Compile เท่านั้น
⚡ Quick Reference¶
#include <iostream>
#include <type_traits>
#include <cstring>
// template <typename T> - ประกาศแบบแผนอินเตอร์เฟซเทมเพลตสำหรับแทนค่าประเภทข้อมูล T
// T maximum(T a, T b) - เนื้อหาฟังก์ชันต้นแบบทั่วไปใช้แทนค่าประเภท T
template <typename T>
T maximum(T a, T b) {
return (a > b) ? a : b;
}
// template <> const char* maximum<const char*>(...) - สเปกจำเพาะของเทมเพลตสำหรับข้อมูลประเภท const char*
template <>
const char* maximum<const char*>(const char* a, const char* b) {
return std::strcmp(a, b) > 0 ? a : b;
}
// const T& - รับส่งอาร์กิวเมนต์แบบอ้างอิงคงที่หลีกเลี่ยงการก๊อปปี้
template <typename T>
const T& maximum_ref(const T& a, const T& b) {
return (a > b) ? a : b;
}
// ประกาศเทมเพลตแบบหลายประเภทข้อมูลร่วมกับระบุขาส่งกลับชัดเจน
template <typename ReturnType, typename T, typename P>
ReturnType mix_add(T a, P b) {
return a + b;
}
// การประยุกต์ใช้ auto return type และ trailing return type ร่วมกับ decltype
template <typename T, typename P>
auto mix_add_deduced(T a, P b) -> decltype((a > b) ? a : b) {
return (a > b) ? a : b;
}
// decltype(auto) - คาดเดาประเภทโดยประคับประคองสถานะ reference
template <typename T>
decltype(auto) get_ref_value(T& ref) {
return ref;
}
// ฟังก์ชันเทมเพลตย่อของ C++20 โดยใช้พารามิเตอร์เป็น auto
auto generic_auto(auto a, auto b) {
return a + b;
}
// Non-type template parameter (NTTP)
template <typename T, size_t size>
bool is_valid(T arr[size]) {
return size > 0;
}
int main() {
// static_assert - ตรวจสอบคุณสมบัติข้อมูลขณะประมวลผลช่วง Compile-time
static_assert(std::is_integral_v<int>, "Integer required");
// maximum<T>(a, b) - เรียกฟังก์ชันโดยระบุประเภทอาร์กิวเมนต์ตรงตัว
auto res = maximum<double>(10, 20.5);
// if constexpr - คำสั่งแยกเงื่อนไขทำงานในระดับ Compile-time
if constexpr (sizeof(int) == 4) {
// โค้ดส่วนนี้จะทำงานต่อเมื่อเป็นระบบแบบ 32-bit int เท่านั้น
}
return 0;
}
🧠 Core Concepts¶
- Template Blueprints: Function Template ทำหน้าที่เป็นโครงร่าง (Blueprint) สำหรับสร้างโค้ด โดย Compiler จะแปลงเป็นโค้ดจริง (Instantiation) เฉพาะกับชนิดข้อมูลที่มีการเรียกใช้งานตอน Compile เท่านั้น
- Type Deduction & Homogeneity: Compiler จะคาดเดาประเภทข้อมูลอาร์กิวเมนต์โดยอัตโนมัติ แต่พารามิเตอร์ประเภท
Tร่วมกันในฟังก์ชันต้องประเมินออกมาเป็นประเภทเดียวกัน (Homogeneous) เสมอ - Specialization & Customization: Full Template Specialization ช่วยให้เราสามารถออกแบบตรรกะเฉพาะเจาะจงกับประเภทข้อมูลบางตัวได้ (เช่น
const char*) ซึ่งจะแซงหน้าตรรกะทั่วไปของ Template
⚠️ Pitfalls (Quick Scan)¶
| ข้อผิดพลาด | วิธีแก้ |
|---|---|
ส่งอาร์กิวเมนต์คนละประเภทไปยัง Template ที่รับพารามิเตอร์เดี่ยว T |
เรียกใช้งานโดยระบุประเภทตรงๆ เช่น maximum<double>(a, c) |
| ใช้ตัวดำเนินการที่ไม่รองรับภายในบล็อกคำสั่งของ Template | มั่นใจว่าชนิดข้อมูลทุกตัวที่ส่งเข้ามาสนับสนุนตัวดำเนินการภายในลูป |
ส่งข้อมูลประเภท const char เข้าไปประมวลผลใน Template เปรียบเทียบค่าทั่วไป |
เขียนสเปกจำเพาะ (Specialization) โดยใช้ std::strcmp สำหรับ const char* |
ประกาศทำ Overload ชนิดรับส่งตามมูลค่า (T) คู่กับรับส่งอ้างอิง (const T&) |
เลือกวิธีการรับส่งพารามิเตอร์แบบใดแบบหนึ่ง แนะนำใช้ const T& |
พยายามแก้ไขค่าตัวแปรใน Template ที่รับพารามิเตอร์เป็นแบบ const T& |
หลีกเลี่ยงการเปลี่ยนแปลงค่าตัวแปรประเภทคงที่ |
| กำหนดประเภทของตัวแปรรับค่าฟังก์ชันแคบกว่าชนิดผลลัพธ์ของ Template | ใช้ Keyword auto ในการประกาศตัวแปรมารับผลลัพธ์การประมวลผล |
| ส่งพอยน์เตอร์ไปยังฟังก์ชัน Template ที่เขียนขึ้นเพื่อเปรียบเทียบค่าข้อมูล | ถอดตัวอ้างอิงพอยน์เตอร์ (Dereference) ก่อนส่ง หรือเขียน specialization |
| คาดหวังให้การตรวจสอบ Compile ตรวจเจอข้อผิดพลาดใน Template ที่ไม่ได้ใช้งาน | เรียกใช้งานฟังก์ชันล่วงหน้าด้วยประเภทข้อมูลต่างๆ เพื่อดักจับบั๊ก |
📖 Full Details¶
Cause → Effect → Fix พร้อม timestamp (คลิกเพื่อดู)
* **ส่งอาร์กิวเมนต์คนละประเภทไปยัง Template ที่รับพารามิเตอร์เดี่ยว `T`** -> **เกิด Compile-time error แจ้งเตือนว่าหาข้อตกลงประเภทข้อมูลขัดแย้งกัน** -> **เรียกใช้งานโดยระบุประเภทตรงๆ เช่น `maximum📎 Repo Files¶
24.FunctionTemplates/24.2TryingOutFunctionTemplates/main.cpp24.FunctionTemplates/24.3TemplateTypeDeductionAndExplicitArguments/main.cpp24.FunctionTemplates/24.4TemplateTypeParametersByReference/main.cpp24.FunctionTemplates/24.5TemplateSpecialization/main.cpp24.FunctionTemplates/24.6FunctionTemplatesWithOverloading/main.cpp24.FunctionTemplates/24.7FunctionTemplatesWithMultipleParameters/main.cpp24.FunctionTemplates/24.8TemplateReturnTypeDeductionWithAuto/main.cpp24.FunctionTemplates/24.9DecltypeAndTrailingReturnTypes/main.cpp24.FunctionTemplates/24.10DecltypeAuto/main.cpp24.FunctionTemplates/24.11DefaultArguments/main.cpp24.FunctionTemplates/24.12NonTypeTemplateParameters/main.cpp24.FunctionTemplates/24.13AutoFunctionTemplates/main.cpp24.FunctionTemplates/24.14NamedTemplateParametersForLambdas/main.cpp24.FunctionTemplates/24.15TypeTraits/main.cpp24.FunctionTemplates/24.16ConstexprIf/main.cpp