C++静态断言 static_assert
在C++标准C++03(ISO/IEC 14882-2003)中,我们可以使用两种断言:
1. 使用预处理中的条件编译和#error指令,可以在预处理阶段检查一些编译条件
2. 可以使用宏assert来进行运行时检查,以确保程序逻辑的正确性方法不能够对模板参数进行检查,因为模板实例化是在编译时进行,而#error方法是在预处理阶段进行的。而assert宏是在运行时进行检查。能不能在编译时检查呢? 于是,静态断言应运而生。
#error
其实,BOOST对静态断言已支持多年(BOOST_STATIC_ASSERT),其内部实现中大量使用了静态断言。另外,在Modern C++ Design书中实现的Loki库也包含了静态断言。但这些实现都有明显的缺陷:
(1)诊断信息不够充分,难于准确定位错误根源(本质上源于它们的实现所限制);
(2)由于实现时需要产生新的类型来表示断言,在某种程序上造成了名字污染。
因此,在新版C++标准(C++0x)中,从语言层面加入了对静态断言的支持,引入了新的关键字static_assert来表示静态断言,并支持如下需求:
(1)编译时处理,不会产生任何运行时开销(包括时间和空间);
(2)断言失败会产生有意义的且充分的诊断信息;
(3)能够在名字空间、类和块的作用域内使用;
(4)易于学习和使用;
(5)误用能够在编译时被发现。
2. 静态断言的使用
静态断言声明的语法形式:static_assert (constant-expression, string-literal); 其中,constant-expression需要是整型常量表达式,string-literal是在断言失败时输出的提示信息。当constant-expression的布尔值为true时,该静态断言声明不会产生任何影响;否则,编译器将给出错误诊断信息。使用静态断言,我们可以在程序的编译时期检测一些条件是否成立,这个特性在调试模板函数的模板参数时特别有用。在编译的时候,模板函数实例化,我们可以使用静态断言去测试模板函数的参数是否按照我们的设计拥有合适的值。例如下面这段代码:(请在vs2010下测试这段代码)
template <int N>
struct Kitten
{
static_assert(N < 2, “Kitten<N> requires N < 2.”);
};
int main()
{
Kitten<1> peppermint;
Kitten<3> jazz;
return 0;
}
当我们在主函数中使用“1”去实例化Kitten这个结构体时,在编译的时候,静态断言static_assert会测试参数N的值,当N的值小于2时就会产生一个断言错误,并将相应的调试帮助信息输出到“Error List”窗口中,这样程序员就可以对问题快速定位,解决问题就更加方便了。
最近在看Ogre源码发现下面的代码也达到了静态断言的目的于是记录一下.
template <size_t Alignment = 0>
class NedAlignedAllocPolicy
{
public:
[Alignment <= 128 && ((Alignment & (Alignment-1)) == 0) ? +1 : -1];
static inline void* allocateBytes(size_t count,
const char* file = 0, int line = 0, const char* func = 0)
{
return NedAllocImpl::allocBytesAligned(Alignment, count, file, line, func);
}
static inline void deallocateBytes(void* ptr)
{
NedAllocImpl::deallocBytesAligned(Alignment, ptr);
}
static inline size_t getMaxAllocationSize()
{
return std::numeric_limits<size_t>::max();
}
private:
NedAlignedAllocPolicy()
{ }
};
typedef int IsValidAlignment
[Alignment <= 128 && ((Alignment & (Alignment-1)) == 0) ? +1 : -1];
是一个静态断言..在编译期判断Alignment的值是否是小于等于128的偶数 .
