3

我对以下问题感到困惑。我想写一些特征结构来测试某个类是否派生自另一个。这可以通过 boost::is_base_of<> 解决。但是,我要测试的基类有一个免费的未定义模板参数。

这是一些代码示例:

template<typename T> class Base {};

class IntDeriv : Base<int> {};

class Foo {};

template< class TestClass >
struct is_derived_from_Base {
   // how to create something that does the following and forces the compiler to deduce T
   static const bool value = boost::is_base_of< Base<T> , TestClass >::value;
};

int main() {
    cout << is_derived_from_Base<Foo> << endl;         // should print 0
    cout << is_derived_from_Base<IntDeriv> << endl;    // should print 1
}

问题是如何推导出T里面Base<T>is_base_of。这可能吗?我闻到了一些 enable_if 但我不知道如何把它放在一起。

4

1 回答 1

3

你想要的都是可能的。使用的技巧在 C++03 中是可能的,但由于你没有指定,我会给你 C++11 版本(使用decltype,在 C++03 中不可用):

template<class TestClass>
struct is_derived_from_Base
{
    template<typename T>
    static std::true_type inherited(Base<T>*);
    static std::false_type inherited(void*);

    static const bool value = decltype(inherited(new TestClass()))::value;
};

你可以在这里看到一个现场版本

那么,它是如何工作的呢?

当结构被实例化并被value需要时,编译器将获得inherited(new TestClass()). 这将调用适当的函数:如果TestClassinherits Base<T>,则TestClass*(由 返回new)可转换为Base<T>*T由编译器自动推导。返回类型是std::true_type. 如果TestClass不继承Base<T>,则选择另一个重载,返回类型为std::false_type。其余的很简单:std::true_type::value = truestd::false_type::value = false.

还有一些极端情况:

  • 使用私有继承会导致编译错误。我不知道如何解决它,因为我不知道答案:如果A私有继承B,A是从B派生的吗?(一般来说,私有继承被认为是一种实现继承)。另请注意,在这种情况下,A* a = new B();将无法编译。
  • 使用私有构造函数会阻止前面解释的技巧正常工作。这将导致编译时错误。由于这违背了该方法的全部要点,因此您必须为此类类找到另一种方法。

请注意,您必须按以下方式使用它:is_derived_from_Base<Foo>::value,而不是您编写的 ( is_derived_from_Base<Foo>)。

于 2013-04-04T13:31:27.427 回答