实现一个模板函数,该函数将两个类作为模板参数,如果继承则返回true

Lea*_*Cpp 4 c++ templates c++11

下面是我遇到的代码,它实际上是std::is_base_of在C++ 11或C++中完成的boost::is_base_of.

辅助函数下面也是这样的:

template<typename D, typename B>
class IsDerivedFromHelper
{
   class No { };
   class Yes { No no[3]; };

   static Yes Test( B* );
   static No Test( ... );
public:
    enum { Is = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) };

};


template <class C, class P> 
bool IsDerivedFrom() {
 return IsDerivedFromHelper<C, P>::Is;
}
Run Code Online (Sandbox Code Playgroud)

有人能解释一下enum的Is作用吗?

什么是静态Yes Test 和静态No Test?它们是功能调用吗?

Ric*_*ges 13

class No { }; - 定义一个类,它将具有未定义的大小,该大小不会为零(由标准强制规定)

class Yes { No no[3]; };- 定义另一个类,Yes它至少是a的3倍No.所以他们保证不同的尺寸.

static Yes Test( B* );- 声明一个返回a的函数Yes,但不给它一个定义(我们不需要一个).它将匹配任何指向派生自的对象的指针参数B.

static No Test( ... );- 声明一个返回a的函数No(更小,记得?).如果不能满足更具体的一个(上面),则选择过载.它接受任何参数(但如果参数派生自优先选择,则优先选择其他版本B).

sizeof(Test(static_cast<D*>(0)))推断将Test指针传递给a时返回的对象的大小D.如果D是派生的B,那将是一个Yes,否则它将是一个No.

因为'call'是在非推导的上下文中进行的,所以它不被评估(调用),只是被选中并且被推导出返回类型.

其余的可能是不言自明的.事实证明它不是:)

所以这一切都放在这里:

enum { Is = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) };

简而言之,这就是说:

"声明一个叫做常数Is,这将是true,如果在调用测试用的结果D*是,恰好是大小为同一个类型Yes,而且这将是false,如果调用的结果恰好是一个类型,是不同大小.由于上面有两个重载,当D是B或从它派生的任何东西时,Test(D*)会选择Yes返回a 的版本,这Yes显然与a的大小相同Yes.如果没有选择此过载,则更宽松(但是优先级较低)一个将是.那一个返回a No,显然不会与a Yes(根据定义)的大小相同."

为什么Test(...)"优先级低于" Test(B*)(在重载决策方面)?因为它只是.标准定义它.

最后:

template <class C, class P> 
bool IsDerivedFrom() {
 return IsDerivedFromHelper<C, P>::Is;
}
Run Code Online (Sandbox Code Playgroud)

这将创建一个函数,它将为任何两个类类型返回上述测试的结果,C并且P.如果P从a派生,它将返回true,否则返回Cfalse.