我想在编译时定义一些缓冲区并使用 static_assert 检查它们的大小:
struct Buffer{
int* array;
size_t size;
};
template<typename T, int size>
struct ConstArray{
T arr[size];
constexpr ConstArray(T t[size]):arr(){
for(int e = 0; e < size; e++)
arr[e] = t[e];
}
constexpr const T& operator[](size_t e)const{
return &arr[e];
}
};
struct A {
Buffer* b;
};
constexpr ConstArray<A, 1> a_maps(
(A[]){(Buffer[]){(int[]){0,1,2}, 3}} // error: constexpr variable 'a_maps' must be initialized by a constant expression
);
int main()
{
static_assert(a_maps[0].b->size == 3, "NOP"); // error: static assertion expression is not an integral constant expression
return 0;
}
有什么建议可以使这种方法可行吗?
(A[]){/*...*/}
和 (int[]){0,1,2}
和 不是有效的标准 C++ 语法。您的编译器仅支持它们作为名为“复合文字”的扩展,它来自 C。
因为标准对这种语法一无所知,所以争论你的代码是否应该是常量表达式几乎毫无意义。这完全取决于编译器。
在 C++ 代码中使用它们不是一个好主意,因为复合文字
看起来类似于 C++ 中的T{...}
语法,但在 C 中它们的行为实际上非常不同。它们具有不同的存储期限、生命周期和价值类别。因此,现在还不清楚 C++ 扩展的行为是否类似于 C 中的 C 语法,或者是否更类似于 C++ 结构。需要在编译器文档中进行验证,以免意外导致UB。
-pedantic-errors
进行编译,让 GCC 和 Clang 在 C++ 模式下抱怨此扩展(如果您只想警告,则使用
-pedantic
)。