【问题标题】:Please help me understand this syntax (implementing static assert in C++)请帮助我理解这个语法(在 C++ 中实现静态断言)
【发布时间】:2010-06-23 06:45:57
【问题描述】:
此语法被用作this question 答案的一部分:
template <bool>
struct static_assert;
template <>
struct static_assert<true> {}; // only true is defined
#define STATIC_ASSERT(x) static_assert<(x)>()
我不懂那种语法。它是如何工作的?
假设我这样做
STATIC_ASSERT(true);
它被转换成
static_assert<true>();
现在呢?
【问题讨论】:
标签:
c++
templates
syntax
metaprogramming
【解决方案1】:
STATIC_ASSERT(true);
确实意味着
static_assert<true>();
计算结果为空。 static_assert<true> 只是一个没有任何成员的空结构。 static_assert<true>() 创建该结构的对象并且不将其存储在任何地方。
这只是编译并且什么都不做。
另一方面
STATIC_ASSERT(false);
意思
static_assert<false>();
这会导致编译错误。 static_assert 没有针对 false 的专业化。所以使用了一般形式。但一般形式如下:
template <bool>
struct static_assert;
这只是一个结构的声明,而不是它的定义。所以static_assert<false>() 在尝试创建一个未定义结构的对象时会导致编译错误。
【解决方案2】:
static_assert<true>(); 做到了
template <>
struct static_assert<true> {}
模板结构特化临时对象创建正在完成 - 调用构造函数,然后调用析构函数,这两者都有望被优化器消除,因为它们什么都不做。由于只有 true 的特化,并且没有模板结构的通用版本,所有计算结果为 static_assert<false>(); 的构造都不会编译。
【解决方案3】:
在表达式中
static_assert<true>();
由于static_assert<true>是一个类型,它会调用static_assert<true>的构造函数。由于static_assert<true> 专门用于空结构,因此不会受到任何影响。
然而,在
static_assert<false>();
因为static_assert<false> 没有特化,所以通用定义
template <bool>
struct static_assert;
将被使用。但在这里,static_assert<B> 类型是不完整。所以调用static_assert<B>的构造函数会导致编译错误。
因此,这称为“静态断言”,因为如果表达式的计算结果为 false,该语句将中止编译,类似于将在运行时终止程序的 normal assert() function。
【解决方案4】:
嗯,我想这是关于模板专业化的。 STATIC_ASSERT(true) 会编译成功,因为有“static_assert”的定义(不仅仅是声明)。
STATIC_ASSERT(false) 将被编译器拒绝,因为只有“static_assert”的声明,没有定义。
更新:对于 Visual Studio,STATIC_ASSERT(true) 是可以的,但是 STATIC_ASSERT(false) 会触发错误:“error C2514: 'static_assert<__formal>' : class has no constructors [ with __formal = false ]”