编译时模板限制C++

Compile Time Template restriction C++

本文关键字:C++ 编译      更新时间:2023-10-16

基本上我有4个类:

  • OverVoid
  • Meta:继承OverVoid
  • 物理:与上述无关
  • 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成为私有或不可访问的基础。如果你想要求它是一个公共基地,你可以要求:

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

您可以隐藏非OverVoid 类型的类的模板定义

template<typename _Ty, 
         class = typename std::enable_if<std::is_base_of<OverVoid, _Ty>::value>::type>
class Move{
};

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

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;
}

输出:

错误:在"struct-std::enable_if"中没有名为"type"的类型

typedef typename std::enable_if::value,_Ty>::type类型;

活样本。

这是一个非常好的解决方案,因为它不能被欺骗——Move的额外模板参数总是可以手动指定的(除非OverVoidMeta没有向客户端公开(。