【问题标题】:can templates be used to detect inheritance relationship模板可以用来检测继承关系吗
【发布时间】:2014-07-23 05:02:55
【问题描述】:

假设我有以下代码(C++):

template < class Td, class Ud, class Vd>
class Extractor
{
private: 
  // some code here
public:
  // the class has functions to populate these vectors
  vector<Td* >    list_of_layers;
  vector<Ud* >    list_of_resistors;
  vector<Vd* >    list_of_nodes;
}

我希望限制用于在实例化类 Extractor 的对象时替换 Td、Ud 和 Vd 的类总是派生从类(例如)T、U 和 V,分别。有可能吗?

【问题讨论】:

标签: c++ templates inheritance


【解决方案1】:

您可以将type_traits 尤其是enable_ifis_base_of 结合使用,如下例所示:

#include <type_traits>

class BaseT {};
class BaseU {};
class BaseV {};

class DerivedT : public BaseT {};
class DerivedU : public BaseU {};
class DerivedV : public BaseV {};

template < class Td, class Ud, class Vd, class Enable = void>
class Extractor {
  static_assert(std::is_base_of<BaseT, Td>::value, "Template argument Td is not derived from BaseT");
  static_assert(std::is_base_of<BaseU, Ud>::value, "Template argument Ud is not derived from BaseU");
  static_assert(std::is_base_of<BaseV, Vd>::value, "Template argument Vd is not derived from BaseV");
};

template <class Td, class Ud, class Vd>
class Extractor<Td, Ud, Vd, 
  typename std::enable_if<std::is_base_of<BaseT, Td>::value &&
                          std::is_base_of<BaseU, Ud>::value &&
                          std::is_base_of<BaseV, Vd>::value>::type> {

};

int main() {
  Extractor<DerivedT, DerivedU, DerivedV> dummy;
  Extractor<int, double, int> dummy2; // will fail to compile!!!
}

LIVE DEMO

【讨论】:

  • 很好,但类型匹配失败时的错误消息非常具有误导性。
  • 感谢现场演示和对问题的反馈! @40two:由于我是新手,请您稍微解释一下代码,例如各个部分如何组合在一起以及为什么(似乎)我们有两个类 Extractor 的定义?
  • @Chatter 实际上我们没有两个定义,而是一个模板定义和一个模板专业化。当您定义Extractor 类型的对象时,C++ 将首先尝试与模板特化匹配。如果满足enable_if 中的条件,则“OK Charlie good to go”,如果不满足enable_if 中的条件(即,模板参数不是从特定类派生的)C++ 将尝试实例化Extractor具有来自Extractor 定义的提供参数的对象。但是,由于 static_asserts 带有特定的错误消息 HTH :),这将失败。
  • 顺便说一句,std::enable_if 在这里没用,static_assert 就足够了。
【解决方案2】:

是的。您可以为此使用 std::is_base_of 特征。 向您的类添加静态断言,例如:

static_assert(std::is_base_of<T, Td>::value, "Td must inherit from T");

【讨论】:

    猜你喜欢
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多