หากคุณต้องการเรียกใช้ฟังก์ชันf
สำหรับทุกประเภทที่มีสมาชิกฟังก์ชันgetInt
ไม่ใช่แค่X
คุณสามารถประกาศ 2 โอเวอร์โหลดสำหรับฟังก์ชั่นf
:
สำหรับประเภทที่มีgetInt
ฟังก์ชั่นสมาชิกรวมถึงชั้นเรียนX
สำหรับทุกประเภทอื่น ๆ Y
รวมทั้งระดับ
โซลูชัน C ++ 11 / C ++ 17
เมื่อนึกไว้แล้วคุณสามารถทำสิ่งนี้:
#include <iostream>
#include <type_traits>
template <typename, typename = void>
struct has_getInt : std::false_type {};
template <typename T>
struct has_getInt<T, std::void_t<decltype(((T*)nullptr)->getInt())>> : std::is_convertible<decltype(((T*)nullptr)->getInt()), int>
{};
class X {
public:
int getInt(){
return 9;
}
};
class Y {};
template <typename T,
typename std::enable_if<!has_getInt<T>::value, T>::type* = nullptr>
void f(T& v) {
// only for Y
std::cout << "Y" << std::endl;
}
template <typename T,
typename std::enable_if<has_getInt<T>::value, T>::type* = nullptr>
void f(T& v){
// only for X
int i = v.getInt();
std::cout << "X" << std::endl;
}
int main() {
X x;
f(x);
Y y;
f(y);
}
ตรวจสอบออกสด
โปรดทราบว่าstd::void_t
มีการนำมาใช้ใน C ++ 17 แต่ถ้าคุณถูก จำกัด ไว้ที่ C ++ 11 มันจะง่ายต่อการติดตั้งvoid_t
ด้วยตัวเอง:
template <typename...>
using void_t = void;
และนี่คือ C ++ 11 รุ่นสด
เรามีอะไรใน C ++ 20
C ++ 20 นำจำนวนมากของสิ่งที่ดีและหนึ่งในนั้นคือแนวคิด เหนือสิ่งที่ใช้ได้สำหรับ C ++ 11 / C ++ 14 / C ++ 17 สามารถลดลงอย่างมากใน C ++ 20:
#include <iostream>
#include <concepts>
template<typename T>
concept HasGetInt = requires (T& v) { { v.getInt() } -> std::convertible_to<int>; };
class X {
public:
int getInt(){
return 9;
}
};
class Y {};
template <typename T>
void f(T& v) {
// only for Y
std::cout << "Y" << std::endl;
}
template <HasGetInt T>
void f(T& v){
// only for X
int i = v.getInt();
std::cout << "X" << std::endl;
}
int main() {
X x;
f(x);
Y y;
f(y);
}
ตรวจสอบออกสด
type_info
โครงสร้างมีตัวดำเนินการเปรียบเทียบความเท่าเทียมกันดังนั้นtypeid(T) == typeid(X)
ควรทำงานเช่นกัน