给出以下代码序列:
#include <iostream>
using namespace std;
template <typename T>
class Base
{
public:
T* t;
void b() {}
};
class D1:
public Base<D1>
{
public:
int d1;
};
class D2:
public D1
{
public:
int d2;
};
template <typename T>
class Selector
{
public:
template <typename U>
void a(Base<U>& base)
{
cout << __LINE__ << endl;
base.b();
}
template <typename U>
void a(U& u)
{
cout << __LINE__ << endl;
}
};
int main()
{
D2 derivated;
Selector<D2> s;
s.a(derivated);
return 0;
}
我想检查一些类(D2)是否有基类(Base),是否继承了任何D2父类。
我无法让Selector
找到最专业的成员函数。
答案 0 :(得分:3)
您可以装配自己的特征来检查某个类型是否具有任何 Base<T>
作为祖先。以下适用于我:
template <typename T> struct Foo { };
struct Bar : Foo<Bar> { };
struct Zip : Bar { };
#include <type_traits>
template <typename T>
class derives_from_any_foo
{
typedef char yes;
typedef char no[2];
template <typename U>
static yes & test(Foo<U> const &);
static no & test(...);
public:
static bool const value = sizeof(test(std::declval<T>())) == sizeof(yes);
};
#include <iostream>
int main()
{
std::cout << "int: " << derives_from_any_foo<int>::value << "\n"
<< "Bar: " << derives_from_any_foo<Bar>::value << "\n"
<< "Zip: " << derives_from_any_foo<Zip>::value << "\n";
}
通常不需要为这种类型的检查要求任何对象实例;一切都只是静态的。如果您有一个对象,请使用decltype
来获取其类型,或者添加一个类型推导辅助函数。
答案 1 :(得分:1)
这种情况正在发生,因为与U = D2
相比U = D1
是更好的候选者(即Base<D1>
)。你将无法使用相同的函数定义来实现这一点,因为第一个替代方案总是超过第二个。
更新:如果您允许更改class Selector
,请按以下SFINAE方式进行调整以使其正确:
template<bool> struct Bool;
template <typename T, typename = Bool<true> >
class Selector // <---- For general cases
{
public:
template <typename U>
void a(U& u) // <---- choose normal funciton
{
cout << __LINE__ << endl;
}
};
template <typename T>
class Selector<T,Bool<IsAnyPublicBaseof<T,Base>::value> >
{ // <---- For the cases like `class D2`
public:
template <typename U>
void a(Base<U>& base) // <--- choose special function
{
cout << __LINE__ << endl;
base.b();
}
};
内部SFINAE是,
template<typename T, template<typename> class Base>
struct IsAnyPublicBaseOf
{
typedef char (&yes)[2];
template<typename X>
static yes Check (Base<X>*);
static char Check (...);
static const bool value = (sizeof(Check((T*)0)) == sizeof(yes));
};
这是working demo,完全您的代码。
另请注意,您无需确定Selector
对象。只需将Selector::a()
设为static
方法,并使用法简单:
Selector<D2>::a(derivated);