【问题标题】:Check if template argument is inherited from class检查模板参数是否从类继承
【发布时间】:2019-07-10 22:41:29
【问题描述】:

我想检查给模板的类型是否继承自我项目中的基类。

它应该像从以下示例中所期望的那样工作:

template< class T : public CBaseClass >
  • 是否可以使用模板来做到这一点,如果没有,我还能怎么做?

【问题讨论】:

标签: c++ templates


【解决方案1】:

Followingexample from Stroustrup:

template<class Test, class Base>
struct AssertSameOrDerivedFrom {
  AssertSameOrDerivedFrom() { &constraints; }
public:
  static void constraints() {
    Test *pd = 0;
    Base *pb = pd;
  }
};

template<class T>
struct YourClass {
  YourClass() {
    AssertSameOrDerivedFrom<T, CBaseClass>();
  }
};

在 C++0x 中,这变成:

template<class T>
struct YourClass {
  static_assert(std::is_base_of<CBaseClass, T>::value);
};

【讨论】:

  • @CrazyEddie:鉴于问题中的代码示例,我相信 OP 通过“检查”表示“断言”,而不是“如果 C 则执行 X,否则 Y”。
【解决方案2】:

您可以使用 Boost 中的 boost::is_base_and_derivedBOOST_STATIC_ASSERT。如果您使用支持 TR1 或 C++0x 的编译器,标准库中有这些构造的等价物(std::is_base_of 和 C++0x 中的 static_assert 语句)。

【讨论】:

  • 不幸的是,我不允许使用 boost
  • @Oktstrom:你用的是什么编译器?支持TR1还是C++0x?
  • 我使用的是Visual Studio 2010自带的编译器
  • 看看你里面是否有&lt;type_traits&gt;标头和std::is_base_of模板。
【解决方案3】:

如果您想断言,请按照 Nurk 的方式进行。如果要检查,请使用 boost 或 C++0x 中的 is_base_of。如果您不能使用其中任何一个,请使用 SFINAE:

template < typename Base, typename PotentialDerived >
struct is_base
{
  typedef char (&no)  [1];
  typedef char (&yes) [2];

  static yes check(Base*);
  static no  check(...);

  enum { value = sizeof(check(static_cast<PotentialDerived*>(0))) == sizeof(yes) };
};

【讨论】:

    【解决方案4】:

    越短越好:

    template <typename Base, typename Derived>
    struct is_base {
        constexpr static bool check(Base*)   { return true; }
        constexpr static bool check(...)     { return false; }
        enum { value = check(static_cast<Derived*>(0)) };
    };
    

    示例 1:

    struct A {};
    struct B  : A { };
    
    int main(void) {
        static_assert(is_base<A,B>::value, "If Error: A is not base of B");
    }
    

    示例 2:

    template <bool, typename T=void>
    struct Use {
        static std::string info() { return "Implementation that consider that A is not base of B"; }
    };
    
    template <typename T>
    struct Use<true,T>  {
        static std::string info() { return "Implementation that consider that A is the base of B"; }
    };
    
    
    int main(void) {
        std::cout << Use<is_base<A,B>::value>::info(); //Implementation that consider that A is the base of B
    }
    

    【讨论】:

      猜你喜欢
      • 2014-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-30
      • 1970-01-01
      • 1970-01-01
      • 2018-05-23
      相关资源
      最近更新 更多