编译时模板限制 C++
Compile Time Template restriction C++
基本上我有 4 classes:
- 虚空
- Meta:继承了OverVoid
- 物理:与上述无关
- 移动:模板化class
我希望 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;
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;
};
每种类型都会出现编译时错误,不是 OverVoid
或 Meta
(或者,更一般地说,对于每个 T
,其中 is_overvoid_or_meta<T>::value
是 false
- 如果您将来要添加更多,您可能希望将 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;
这是一个非常好的解决方案,因为它无法被欺骗 - Move
的附加模板参数始终可以手动指定(除非 OverVoid
和 Meta
未向客户端公开) .
基本上我有 4 classes:
- 虚空
- Meta:继承了OverVoid
- 物理:与上述无关
- 移动:模板化class
我希望 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;
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;
};
每种类型都会出现编译时错误,不是 OverVoid
或 Meta
(或者,更一般地说,对于每个 T
,其中 is_overvoid_or_meta<T>::value
是 false
- 如果您将来要添加更多,您可能希望将 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;
这是一个非常好的解决方案,因为它无法被欺骗 - Move
的附加模板参数始终可以手动指定(除非 OverVoid
和 Meta
未向客户端公开) .