รูปแบบ enable_if
จำกัดเทมเพลตด้วยวิธีดั้งเดิม
รูปแบบ enable_if เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน
enable_if คืออะไร
std::enable_if เป็นคุณลักษณะขนาดเล็กที่กำหนดสมาชิก type แบบมีเงื่อนไข เมื่อเงื่อนไขเป็นจริง ชนิดนั้นจะมีอยู่ แต่เมื่อเป็นเท็จ แม่แบบที่ครอบอยู่จะถูกนำออกด้วย SFINAE
- อยู่ใน
<type_traits> - เป็นเครื่องมือคลาสสิกสำหรับกำหนดข้อจำกัดให้แม่แบบ
#include <iostream>
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
doubleIt(T v) { return v * 2; }
int main() {
std::cout << doubleIt(21) << '\n';
return 0;
}วิธีการทำงาน
enable_if<Cond, T>::type จะเป็น T ก็ต่อเมื่อ Cond เป็นจริง หากเป็นเท็จ จะไม่มีสมาชิก type ดังนั้นการแทนที่จึงล้มเหลว
#include <iostream>
#include <type_traits>
int main() {
std::cout << std::boolalpha;
std::cout << std::is_same<std::enable_if<true, int>::type, int>::value << '\n';
return 0;
}enable_if ในชนิดผลลัพธ์
ตำแหน่งที่ใช้กันมากที่สุดคือชนิดผลลัพธ์ ฟังก์ชันจะมีอยู่ก็ต่อเมื่อเงื่อนไขเป็นจริง
#include <iostream>
#include <type_traits>
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
half(T v) { return v / 2; }
int main() {
std::cout << half(5.0) << '\n';
return 0;
}enable_if ในฐานะพารามิเตอร์แม่แบบ
รูปแบบการเขียนอีกแบบหนึ่งใส่ enable_if ไว้ในพารามิเตอร์แม่แบบที่มีค่าเริ่มต้น ทำให้ชนิดผลลัพธ์อ่านได้สะอาดขึ้น
#include <iostream>
#include <type_traits>
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
T triple(T v) { return v * 3; }
int main() {
std::cout << triple(4) << '\n';
return 0;
}ทางลัด enable_if_t
C++14 เพิ่มนามแฝง std::enable_if_t<Cond, T> เพื่อให้คุณไม่ต้องเขียนส่วนเกินอย่าง typename ...::type
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, T>
negate(T v) { return -v; }
int main() {
std::cout << negate(8) << '\n';
return 0;
}การจับคู่โอเวอร์โหลดสองรายการ
จัดเตรียมเงื่อนไขที่เสริมกัน เพื่อให้โอเวอร์โหลดที่ถูกต้องมีเพียงหนึ่งรายการสำหรับทุกชนิดและไม่เกิดความกำกวม
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, const char*>
category() { return "integer"; }
template <typename T>
std::enable_if_t<!std::is_integral<T>::value, const char*>
category() { return "non-integer"; }
int main() {
std::cout << category<int>() << ' ' << category<double>() << '\n';
return 0;
}การรวมเงื่อนไข
ใช้ตัวดำเนินการเชิงตรรกะกับค่าคุณลักษณะ เพื่อแสดงข้อจำกัดที่ซับซ้อนขึ้น เช่น "เป็นจำนวนเต็มและมีเครื่องหมาย"
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, T>
magnitude(T v) { return v < 0 ? -v : v; }
int main() {
std::cout << magnitude(-12) << '\n';
return 0;
}การกำหนดข้อจำกัดให้ตัวสร้าง
คุณสามารถใส่ enable_if ไว้ในพารามิเตอร์แม่แบบของตัวสร้าง เพื่ออนุญาตให้ใช้ตัวสร้างได้เฉพาะกับชนิดที่เข้ากันได้
#include <iostream>
#include <type_traits>
struct Wrapper {
int value;
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
Wrapper(T v) : value(static_cast<int>(v)) {}
};
int main() {
Wrapper w(42);
std::cout << w.value << '\n';
return 0;
}ข้อผิดพลาดจากอาร์กิวเมนต์แม่แบบเริ่มต้น
โอเวอร์โหลดสองรายการที่แตกต่างกันเพียงพารามิเตอร์แม่แบบ enable_if ที่มีค่าเริ่มต้น จะถูกมองว่าเป็นการประกาศซ้ำ ให้ใช้รูปแบบที่แตกต่างกัน (เช่น ใส่เงื่อนไขหนึ่งรายการไว้ในชนิดผลลัพธ์)
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
printKind() { std::cout << "int\n"; }
template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
printKind() { std::cout << "float\n"; }
int main() {
printKind<int>();
printKind<double>();
return 0;
}การเปรียบเทียบกับ Concepts
แนวคิดของ C++20 แทนที่การใช้ enable_if ส่วนใหญ่ด้วยไวยากรณ์ที่ชัดเจนกว่ามาก แต่ enable_if ยังคงจำเป็นสำหรับโค้ดก่อน C++20 และกรณีขอบบางกรณี
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_arithmetic<T>::value, T>
square(T v) { return v * v; }
int main() {
std::cout << square(6) << ' ' << square(1.5) << '\n';
return 0;
}ตัวอย่างสมบูรณ์
นำทุกอย่างมารวมกัน: กลุ่มฟังก์ชันที่จัดรูปแบบจำนวนเต็มและจำนวนทศนิยมแตกต่างกัน โดยเลือกขณะคอมไพล์
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
format(T v) { std::cout << "int[" << v << "]\n"; }
template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
format(T v) { std::cout << "float(" << v << ")\n"; }
int main() {
format(10);
format(3.5);
return 0;
}ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับ enable_if
สรุปทบทวน
คุณได้เรียนรู้รูปแบบคลาสสิกของ enable_if ดังนี้:
- กำหนด
::typeก็ต่อเมื่อเงื่อนไขเป็นจริง ซึ่งช่วยเปิดใช้ SFINAE - วางไว้ในชนิดผลลัพธ์หรือพารามิเตอร์แม่แบบที่มีค่าเริ่มต้น
- ใช้นามแฝง
enable_if_tและรวมคุณลักษณะด้วยตัวดำเนินการเชิงตรรกะ - แนวคิดเข้ามาแทนที่สิ่งนี้ใน C++20 แต่ยังคงมีการใช้งานอย่างแพร่หลาย
หลักสูตรการทำให้แม่แบบจำเพาะและ SFINAE จบลงเพียงเท่านี้
คำถามที่พบบ่อย
บทเรียน “รูปแบบ enable_if” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “รูปแบบ enable_if” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “รูปแบบ enable_if”
จำกัดเทมเพลตด้วยวิธีดั้งเดิม คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “รูปแบบ enable_if” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม
ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การทำให้เฉพาะทางแบบเต็ม
- การทำให้เฉพาะทางบางส่วน
- SFINAE
- รูปแบบ enable_if