带有模板化基类的boost :: is_same

时间:2013-04-04 12:43:54

标签: c++ templates metaprogramming

我对以下问题感到困惑。我想编写一些特征结构来测试某个类是否来自另一个类。这可以通过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>的{​​{1}}。 这有可能吗?我闻到了一些enable_if,但我不确定如何把它放在一起。

1 个答案:

答案 0 :(得分: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;
};

您可以看到live version here

那么,它是如何运作的?

当实例化结构并且需要value时,编译器将获得inherited(new TestClass())的返回类型。这将调用相应的函数:如果TestClass继承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,是否是从B派生的A? (通常,私有继承被视为实现继承)。另请注意,在这种情况下,A* a = new B();将无法编译。
  • 使用私有构造函数可防止先前解释的技巧正常工作。这将导致编译时错误。由于这会破坏这种方法的重点,你必须为这些类找到另一种方法。

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