C++ 如何优雅地检查模板类型是否派生自C+中的特定基类+;11?

C++ 如何优雅地检查模板类型是否派生自C+中的特定基类+;11?,c++,c++11,templates,C++,C++11,Templates,我有一个模板类Context。我想限制用户使用从特定类派生的指定类型(Stratege1,而不是Stratege2) class Base { public: virtual void run() = 0; }; class Stratege1 : public Base { public: virtual void run() { printf("Stratege1 \n"); } }; class Stratege2 { public:

我有一个模板类
Context
。我想限制用户使用从特定类派生的指定类型(
Stratege1
,而不是
Stratege2

class Base {
public: 
    virtual void run() = 0;
}; 
class Stratege1 : public Base {
public:
    virtual void run() {
        printf("Stratege1 \n");
    }
}; 
class Stratege2 {
public:
    virtual void run() {
        printf("Stratege2 \n"); 
    }
}; 
template <typename T> class Context {
public:
    void run() { 
        t.run();
    }; 
private:
    T t;
};
类基{
公众:
虚空运行()=0;
}; 
阶级战略1:公共基础{
公众:
虚拟空运行(){
printf(“策略1\n”);
}
}; 
阶级战略2{
公众:
虚拟空运行(){
printf(“策略2\n”);
}
}; 
模板类上下文{
公众:
无效运行(){
t、 run();
}; 
私人:
T;
};
如果用户希望这样调用,则可以:

Context<Stratege1> context;
context.run();
语境;
context.run();
但是,我不希望用户使用(以避免意外的潜在运行时问题)

语境;
context.run();
因为
Stratege2
不是从
Base
类派生的。在编译过程中有没有优雅的方法来限制这个概念

谢谢你的建议

使用(相当于
std::enable_if::type
)和

#包括
模板
类上下文{
公众:
无效运行(){
t、 run();
}; 
私人:
T;
};
自C++11以来,您可以执行一些操作,这意味着在编译时检查失败时会出现一个不错的编译错误:

#include <type_traits> // is_base_of
template <typename T>
class Context {
    static_assert(std::is_base_of<Base, T>::value,
        "T must be a derived class of Base in Context<T>.");
public:
    void run() { 
        t.run();
    }; 
private:
    T t;
};
#include//is#u base#u of
模板
类上下文{
static_assert(std::是::value的_base_),
“T必须是上下文中基类的派生类。”);
公众:
无效运行(){
t、 run();
}; 
私人:
T;
};
例如:

Context<NotBase> c2;
Context;
错误:静态_断言失败“T必须是上下文中基类的派生类。”
->static_assert(std::是::value的_base_),
注意:在这里请求的模板类“Context”的实例化中
->语境c2;

在编译过程中有没有优雅的方法来限制这个概念

另一种可能的解决方案是通过部分专门化:第二个模板参数是
true
,前提是
T
是从base派生的

template <typename T, bool = std::is_base_of<Base, T>::value>
class Context;

template <typename T>
class Context<T, true>
 {
   private:
      T t;

   public:
      void run () { t.run(); }; 
 };

接受从类基派生的任何类。否则,将拒绝该类。它不限于已知的类型。它只是要求用户按照指定实现模板参数的限制(例如,仅从类基派生)。
static_assert(std::is_Base_of::value,”);
如果要使用的方法是虚拟的,为什么不编写一个简单的非模板函数来处理基类指针呢?这是一个优雅的实现,但不容易理解:-)我不喜欢编译失败的替换错误消息。例如,根据您的建议:
错误:在“struct std::enable_if”
中没有名为“type”的类型。不太明显。这是另一个优雅的实现,非常感谢:-)
Context<NotBase> c2;
error: static_assert failed "T must be a derived class of Base in Context<T>."
    -> static_assert(std::is_base_of<Base, T>::value,
note: in instantiation of template class 'Context<NotBase>' requested here
    -> Context<NotBase> c2;
template <typename T, bool = std::is_base_of<Base, T>::value>
class Context;

template <typename T>
class Context<T, true>
 {
   private:
      T t;

   public:
      void run () { t.run(); }; 
 };
Context<Stratege1>  cs1;    // compile
// Context<Stratege2>  cs2; // compilation error
Context<Stratege2, true> cs2; // compile