代码之家  ›  专栏  ›  技术社区  ›  phant0m Grijesh Chauhan

将C++模板参数限制为子类

  •  63
  • phant0m Grijesh Chauhan  · 技术社区  · 16 年前

    如何强制模板参数 T 成为特定类的子类 Baseclass 像这样:

    template <class T : Baseclass> void function(){
        T *object = new T();
    
    }
    
    7 回复  |  直到 13 年前
        1
  •  56
  •   sepp2k    16 年前

    template <class T> void function(){
        Baseclass *object = new T();
    
    }
    

    如果T不是基类(或T)的子类,则不会编译

        2
  •  85
  •   Vish Desai    12 年前

    使用C++ 11兼容编译器,你可以这样做:

    template<class Derived> class MyClass {
    
        MyClass() {
            // Compile-time sanity check
            static_assert(std::is_base_of<BaseClass, Derived>::value, "Derived not derived from BaseClass");
    
            // Do other construction related stuff...
            ...
       }
    }
    

        3
  •  52
  •   Douglas Leeder    13 年前

    要在运行时执行较少无用的代码,可以查看: http://www.stroustrup.com/bs_faq2.html#constraints

    特别地:

    template<class T, class B> struct Derived_from {
            static void constraints(T* p) { B* pb = p; }
            Derived_from() { void(*p)(T*) = constraints; }
    };
    
    template<class T> void function() {
        Derived_from<T,Baseclass>();
    }
    
        4
  •  11
  •   David Rodríguez - dribeas    16 年前

    template <typename T>
    boost::enable_if< boost::is_base_of<Base,T>::value >::type function() {
       // This function will only be considered by the compiler if
       // T actualy derived from Base
    }
    

    请注意,这将仅在满足条件时实例化函数,但如果不满足条件,则不会提供明显的错误。

        5
  •  9
  •   Community Mohan Dere    6 年前

    因为C++ 11不需要Boost或 static_assert . C++ 11介绍 is_base_of enable_if . C++ 14介绍了方便型 enable_if_t 但是,如果你被C++ 11所困扰,你可以简单地使用 enable_if::type

    备选方案1

    David Rodríguez 的解决方案可以重写如下:

    #include <type_traits>
    
    using namespace std;
    
    template <typename T>
    enable_if_t<is_base_of<Base, T>::value, void> function() {
       // This function will only be considered by the compiler if
       // T actualy derived from Base
    }
    

    备选方案2

    因为C++ 17,我们有 is_base_of_v

    #include <type_traits>
    
    using namespace std;
    
    template <typename T>
    enable_if_t<is_base_of_v<Base, T>, void> function() {
       // This function will only be considered by the compiler if
       // T actualy derived from Base
    }
    

    备选方案3

    你也可以限制整个模板。可以使用此方法定义整个类。请注意 启用\u如果\u t void ,但这并不重要,因为我们没有使用它。

    #include <type_traits>
    
    using namespace std;
    
    template <typename T,
              typename = enable_if_t<is_base_of_v<Base, T>>>
    void function() {
       // This function will only be considered by the compiler if
       // T actualy derived from Base
    }
    

    documentation typename = enable_if_t... 是名称为空的模板参数。我们只是使用它来确保类型的定义存在。特别地, 启用\u如果\u t 如果 Base T .

    本文以上述技术为例 启用\u if .

        6
  •  4
  •   Daniel Trebbien    16 年前

    你可以用 Boost Concept Check BOOST_CONCEPT_REQUIRES

    #include <boost/concept_check.hpp>
    #include <boost/concept/requires.hpp>
    
    template <class T>
    BOOST_CONCEPT_REQUIRES(
        ((boost::Convertible<T, BaseClass>)),
    (void)) function()
    {
        //...
    }
    
        7
  •  0
  •   DanDan    16 年前

    通过调用存在于基类中的模板内的函数。

    如果您尝试用一个无法访问此函数的类型实例化模板,您将收到一个编译时错误。