【问题标题】:Checking Inheritance with templates in C++在 C++ 中使用模板检查继承
【发布时间】:2010-09-08 11:59:12
【问题描述】:

我有一个类,它是一个包装类(用作公共接口),围绕着另一个实现所需功能的类。所以我的代码看起来像这样。

template<typename ImplemenationClass> class WrapperClass {
// the code goes here
}

现在,我如何确保 ImplementationClass 只能从一组类派生,类似于 java 的泛型

<? extends BaseClass>

语法?

【问题讨论】:

    标签: java c++ templates


    【解决方案1】:

    在目前的情况下,除了 cmets 或第三方解决方案之外,没有其他好的方法。 Boost为此提供了concept check library,我认为gcc也有一个实现。概念在 C++0x 改进列表中,但我不确定您是否可以指定子类型 - 它们更多地用于“必须支持这些操作”,这(大致)等效。

    编辑:维基百科有这个section关于 C++0x 中的概念,它比草案提案更容易阅读。

    【讨论】:

      【解决方案2】:

      Stoustrup's own words on the subject

      基本上是一个小类,你在某处实例化,例如模板类构造函数。

      template<class T, class B> struct Derived_from {
          static void constraints(T* p) { B* pb = p; }
          Derived_from() { void(*p)(T*) = constraints; }
      };
      

      【讨论】:

        【解决方案3】:

        它很冗长,但你可以这样做:

        #include <boost/utility/enable_if.hpp>
        #include <boost/type_traits/is_base_of.hpp>
        
        struct base {};
        
        template <typename ImplementationClass, class Enable = void>
        class WrapperClass;
        
        template <typename ImplementationClass>
        class WrapperClass<ImplementationClass,
              typename boost::enable_if<
                boost::is_base_of<base,ImplementationClass> >::type>
        {};
        
        struct derived : base {};
        struct not_derived {};
        
        int main() {
            WrapperClass<derived> x;
        
            // Compile error here:
            WrapperClass<not_derived> y;
        }
        

        这需要一个对标准有良好支持的编译器(最新的编译器应该没问题,但旧版本的 Visual C++ 不行)。如需更多信息,请参阅Boost.Enable_If documentation

        正如 Ferruccio 所说,一个更简单但功能较弱的实现:

        #include <boost/static_assert.hpp>
        #include <boost/type_traits/is_base_of.hpp>
        
        struct base {};
        
        template <typename ImplementationClass>
        class WrapperClass
        {
            BOOST_STATIC_ASSERT((
                boost::is_base_of<base, ImplementationClass>::value));
        };
        

        【讨论】:

        • 您可以使用 BOOST_STATIC_ASSERT 代替 enable_if 使其更清晰一些。即 BOOST_STATIC_ASSERT(boost::is_base_of);
        • 是的,我已经添加了。我更喜欢 enable_if 因为它可以让您拥有不同的版本并提供更好的错误消息(IMO)。有些人也喜欢 MPL 的静态断言中的错误消息。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-17
        • 1970-01-01
        • 2012-10-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多