0Pricing
C++ Academy · บทเรียน

รูปแบบ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การทำให้เฉพาะทางแบบเต็ม
  2. การทำให้เฉพาะทางบางส่วน
  3. SFINAE
  4. รูปแบบ enable_if
← กลับไปที่ C++ Academy