【问题标题】:boost::is_same with templated base classboost::is_same 与模板化基类
【发布时间】:2013-04-04 12:43:54
【问题描述】:

我对以下问题感到困惑。我想写一些特征结构来测试某个类是否是从另一个类派生的。这可以通过 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
}

问题是如何在is_base_of 中推导出Base&lt;T&gt;T。 这可能吗?我闻到了一些 enable_if 的味道,但我不知道如何组合起来。

【问题讨论】:

  • 是的,这也是我的第一个猜测。但是,有几个类似的问题可以通过一些 enable_if/SFINAE 魔法来解决。关键是编译器实际上不需要推导出 T。我只想知道某个类是否从 Base 派生为某个任意 T。
  • @jrok 这是可能的,看我的回答。请注意,该方法可以扩展以查找基的类型。

标签: c++ templates metaprogramming


【解决方案1】:

你想要的都是可能的。使用的技巧在 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&lt;T&gt;,则TestClass*(由new 返回)可转换为Base&lt;T&gt;*T 由编译器自动推导。返回类型为std::true_type。如果TestClass不继承Base&lt;T&gt;,则选择另一个重载,返回类型为std::false_type。其余的很简单:std::true_type::value = truestd::false_type::value = false

还有一些极端情况:

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

请注意,您必须按以下方式使用它:is_derived_from_Base&lt;Foo&gt;::value,而不是您写的 (is_derived_from_Base&lt;Foo&gt;)。

【讨论】:

  • 太棒了。完全有道理。我正朝着那个方向漂移(使用一些函数重载的东西),但没有看到那个解决方案。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多