【发布时间】:2011-10-20 17:20:56
【问题描述】:
对于没有内置 static_assert 的 C++ 版本,有两个 widely used 静态断言实现。
第一个在Boost中使用,使用a template and a specialization of that template:
template <bool> struct static_assert;
template <> struct static_assert<true> {}; // only true is defined
#define STATIC_ASSERT(x) static_assert<(x)>()
这里一旦要检查的条件为假,编译器将无法找到模板的通用版本并且编译失败。
第二个使用typedef:
#define STATIC_ASSERT( x ) typedef char __STATIC_ASSERT__[( x )?1:-1]
一旦违反了检查条件,编译器就会尝试 typedef 一个大小为 -1 的数组,这是非法的,因此会出现编译时错误。
对我来说,后者更好,因为它保证不发出任何代码,而且它可以像这样使用(来自here):
template<int Shift> class BinaryFlag {
STATIC_ASSERT( 0 <= Shift && Shift < sizeof( DWORD) * CHAR_BIT );
public:
static const DWORD FlagValue = static_cast<DWORD>( 1 << Shift );
};
#define BINARY_FLAG( n ) CBinaryFlag<n>::FlagValue
而前者不能那样使用。
有什么理由更喜欢静态断言的前一个实现而不是后一个?
【问题讨论】:
-
+1,但我仍然不明白第一个版本将如何发出代码?这些只是空的
struct声明,对吗? -
@iammilind:有一个临时结构可能会发出一些代码。
-
@sharptooth 类型为空 POD。我看不到任何不省略构造的情况。也就是说,您更喜欢第二种解决方案的另一点是有效的。
-
选择其中一个的另一个原因可能是发生故障时生成的错误有多好。我猜在大多数平台上,即使在这方面,typedef 解决方案也会更好。
-
也不能保证 typedef 不会发出任何代码。例如,允许为分析目的检测其代码的实现在此处发出一些代码,以增加当前源文件行号的记录。那将符合标准。如果您只是在谈论可视化 C++,那么对于每种断言,您都可以使用您感兴趣的编译器选项检查它是否发出代码,我怀疑您会看到启用任何优化的问题。
标签: c++ templates visual-c++ static-assert