编译时模板限制 C++

Compile Time Template restriction C++

基本上我有 4 classes:

我希望 move 的模板只接受 OverVoid 类型的对象,即 OverVoid 和 Meta。

class OverVoid{
public:

    virtual ~OverVoid(){
    };
};

class Meta: public OverVoid{

};

class Physical{
public:
};

template<typename _Ty>
class Move{

};

我想在编译时发现一个错误, 我知道有一种方法可以使用 boost,但我不能使用 Boost(我公司的开发问题)

有什么想法吗?

最简单的就是一个static_assert:

template<typename _Ty>
class Move {
    static_assert(std::is_base_of<OverVoid, _Ty>::value, 
                  "_Ty must inherit from OverVoid.");
};

请注意,这允许 OverVoid 成为私有或不可访问的基地。如果你想要求它是一个 public 基础,你可以改为要求:

    static_assert(std::is_convertible<_Ty*, OverVoid*>::value, 
                  "_Ty must inherit publicly from OverVoid.");

您可以隐藏 class 非 OverVoid

类型的模板定义
template<typename _Ty, 
         class = typename std::enable_if<std::is_base_of<OverVoid, _Ty>::value>::type>
class Move{

};

然后在尝试编译非 OverVoid 类型的 class 时出现错误。

int main() {

  Move<Meta> a;
  Move<OverVoid> b;
  Move<Physical> c;
  // your code goes here
  return 0;
}

错误:

prog.cpp: In function 'int main()':
prog.cpp:29:15: error: no type named 'type' in 'struct std::enable_if<false,    void>'
Move<Physical> c;

使用std::enable_if:

template <typename T>
struct is_overvoid_or_meta
{
     static const bool value = false;
};

template <> struct is_overvoid_or_meta<OverVoid>
{
     static const bool value = true;
};

template <> struct is_overvoid_or_meta<Meta>
{
     static const bool value = true;
};

//Add specialization for all valid types - this allows you to more precisely tell, what types can be used as a template argument for Move

然后:

template<typename _Ty>
class Move
{
     typedef std::enable_if<is_overvoid_or_meta<_Ty>::value, _Ty>::type Type;
};

每种类型都会出现编译时错误,不是 OverVoidMeta(或者,更一般地说,对于每个 T,其中 is_overvoid_or_meta<T>::valuefalse - 如果您将来要添加更多,您可能希望将 is_overvoid_or_meta 更改为更通用的内容,例如 is_acceptable_by_move 或其他内容):

int main()
{
    Move<OverVoid> m1;
    Move<Meta> m2;
    Move<int> m3;
    return 0;
}

输出:

error: no type named 'type' in 'struct std::enable_if'

typedef typename std::enable_if::value, _Ty>::type Type;

Live sample.

这是一个非常好的解决方案,因为它无法被欺骗 - Move 的附加模板参数始终可以手动指定(除非 OverVoidMeta 未向客户端公开) .