Có thể với C++ 11 và decltype
. Để làm điều đó, chúng ta sẽ khai thác rằng một con trỏ tới thành viên không phải là một con trỏ vào lớp dẫn xuất khi thành viên được thừa hưởng từ một lớp cơ sở.
Ví dụ:
struct base{
void f(){}
};
struct derived : base{};
Loại &derived::f
sẽ void (base::*)()
, không void (derived::*)()
. Điều này đã đúng trong C++ 03, nhưng không thể có được loại lớp cơ sở mà không thực sự xác định nó. Với decltype
, thật dễ dàng và chỉ cần chức năng này chút:
// unimplemented to make sure it's only used
// in unevaluated contexts (sizeof, decltype, alignof)
template<class T, class U>
T base_of(U T::*);
Cách sử dụng:
#include <iostream>
// unimplemented to make sure it's only used
// in unevaluated contexts (sizeof, decltype, alignof)
template<class T, class R>
T base_of(R T::*);
struct base{
void f(){}
void name(){ std::cout << "base::name()\n"; }
};
struct derived : base{
void name(){ std::cout << "derived::name()\n"; }
};
struct not_deducible : base{
void f(){}
void name(){ std::cout << "not_deducible::name()\n"; }
};
int main(){
decltype(base_of(&derived::f)) a;
decltype(base_of(&base::f)) b;
decltype(base_of(¬_deducible::f)) c;
a.name();
b.name();
c.name();
}
Output:
base::name()
base::name()
not_deducible::name()
Như ví dụ cuối cùng cho thấy, bạn cần phải sử dụng một thành viên đó thực sự là thành viên được thừa kế của lớp cơ sở mà bạn quan tâm.
Tuy nhiên, nhiều thành viên khác cũng phải xác định rõ ràng một thành viên cấp cơ sở:
struct base2{ void f(){} };
struct not_deducible2 : base, base2{};
int main(){
decltype(base_of(¬_deducible2::f)) x; // error: 'f' is ambiguous
}
Đó là điều tốt nhất bạn có thể nhận được, không cần hỗ trợ trình biên dịch.
Sử dụng ['std :: is_base_of '] (http://stackoverflow.com/questions/2910979/how-is-base-of-works) – iammilind
@iammilind: Đó chỉ là để thử nghiệm nếu một lớp là cơ sở của người khác, bạn phải biết lớp cơ sở để kiểm tra. – Xeo
Bạn cần nó để làm gì? Tôi không nghĩ rằng nó có thể, nhưng có lẽ có cách tiếp cận khác nhau để giải quyết vấn đề thực tế. –