สมมติว่าฉันมีฟังก์ชันเทมเพลตและสองคลาส
class animal {
}
class person {
}
template<class T>
void foo() {
if (T is animal) {
kill();
}
}
ฉันจะตรวจสอบ T คือสัตว์ได้อย่างไร? ฉันไม่ต้องการให้มีบางอย่างที่ตรวจสอบระหว่างเวลาทำงาน ขอบคุณ
สมมติว่าฉันมีฟังก์ชันเทมเพลตและสองคลาส
class animal {
}
class person {
}
template<class T>
void foo() {
if (T is animal) {
kill();
}
}
ฉันจะตรวจสอบ T คือสัตว์ได้อย่างไร? ฉันไม่ต้องการให้มีบางอย่างที่ตรวจสอบระหว่างเวลาทำงาน ขอบคุณ
คำตอบ:
ใช้is_same
:
#include <type_traits>
template <typename T>
void foo()
{
if (std::is_same<T, animal>::value) { /* ... */ } // optimizable...
}
โดยปกติแล้วนั่นเป็นการออกแบบที่ไม่สามารถใช้งานได้โดยสิ้นเชิงและคุณต้องการที่จะเชี่ยวชาญ :
template <typename T> void foo() { /* generic implementation */ }
template <> void foo<animal>() { /* specific for T = animal */ }
โปรดทราบว่าเป็นเรื่องผิดปกติที่จะมีเทมเพลตฟังก์ชันที่มีอาร์กิวเมนต์ที่ชัดเจน (ไม่อนุมาน) ไม่ใช่เรื่องแปลก แต่มักจะมีแนวทางที่ดีกว่า
T
ไม่ได้อนุมานคุณจึงทำอะไรได้ไม่มาก คุณสามารถออกจากแม่แบบหลัก unimplemented is_same
และสร้างความเชี่ยวชาญหรือคุณอาจจะเพิ่มการยืนยันคงที่พร้อม
ฉันคิดว่าวันนี้มันจะดีกว่าที่จะใช้ แต่เฉพาะกับ C ++ 17
#include <type_traits>
template <typename T>
void foo() {
if constexpr (std::is_same_v<T, animal>) {
// use type specific operations...
}
}
หากคุณใช้การดำเนินการเฉพาะบางประเภทใน if expression body โดยไม่มีconstexpr
โค้ดนี้จะไม่คอมไพล์
std::is_same<T, U>::value
ใช้สั้นกว่า:std::is_same_v<T, U>
ใน C ++ 17 เราสามารถใช้ตัวแปรสายพันธุ์
ในการใช้งานstd::variant
คุณต้องรวมส่วนหัว:
#include <variant>
หลังจากนั้นคุณสามารถเพิ่มstd::variant
โค้ดของคุณได้ดังนี้:
using Type = std::variant<Animal, Person>;
template <class T>
void foo(Type type) {
if (std::is_same_v<type, Animal>) {
// Do stuff...
} else {
// Do stuff...
}
}
type
ซึ่งเป็นค่าประเภทType
หรือแม่แบบซึ่งไม่ได้ทำให้ความรู้สึกที่นี่) ไม่ได้มีความหมายในบริบทของis_same_v
variant
ที่สอดคล้องกัน "ลักษณะ" holds_alternative
เป็น
std::variant
ไม่จำเป็นโดยสิ้นเชิงที่นี่
คุณสามารถเชี่ยวชาญเทมเพลตของคุณโดยพิจารณาจากสิ่งที่ส่งไปยังพารามิเตอร์เช่นนี้:
template <> void foo<animal> {
}
T
โปรดทราบว่านี้จะสร้างฟังก์ชั่นใหม่ทั้งหมดขึ้นอยู่กับชนิดที่ผ่านการเป็น โดยปกติแล้วจะดีกว่าเนื่องจากช่วยลดความยุ่งเหยิงและเป็นเหตุผลหลักที่เรามีเทมเพลตตั้งแต่แรก