如何 static_assert std::array 成员的大小
How to static_assert the size of a std::array member
我想明确说明成员变量的数组大小限制,以防止其他人不小心做出愚蠢的更改。以下天真的尝试将无法编译:
struct Foo
{
std::array< int, 1024 > some_array;
static_assert( (some_array.size() % 256) == 0, "Size must be multiple of 256" );
//^ (clang) error: invalid use of non-static data member 'some_array'
};
即使 std::array::size
是一个 constexpr,我也不能像那样直接使用 static_assert
,因为函数和我的成员变量都不是静态的。
我想到的解决方案是使用 decltype
(因为我不想对数组进行类型定义),如下所示:
static_assert( (decltype(some_array)().size() % 256) == 0, "Size must be multiple of 256" );
这看起来像是在默认构造一个 rvalue,我认为它不是 constexpr。
为什么这样做?
是否有更简洁的方法来实现静态断言?
std::array::size
是 constexpr
并且应该与 static_assert
一起工作,但是它在这个特定的上下文中不起作用(即在 class 定义中)因为 some_array
是一个非静态成员变量。
对于这个特定的上下文,您可以使用自制的类型特征在编译时获取大小,如下所示:
template<typename>
struct array_size;
template<typename T, std::size_t N>
struct array_size<std::array<T, N>> {
static const std::size_t size = N;
};
和static_assert
为:
static_assert(array_size<decltype(some_array)>::size % 256) == 0, "Size must be multiple of 256" );
because neither the function nor my member variable is static.
对。问题是静态断言不能引用非静态成员,因为 some_array.size()
等同于 this->some_array.size()
并且 class 范围内没有 this
指针(仅在函数声明符和默认成员初始值设定项内部)。
但是,说 decltype(array_size)
是可以的,因为这实际上并不是要引用对象 array_size
或调用它的成员函数,它只是查询在中声明的名称的类型class.
This looks like it's default-constructing an rvalue, which I didn't think is a constexpr.
array<int, N>
是字面量类型,所以可以用常量表达式构造。您正在构造一个右值这一事实并不重要,您可以构造一个文字类型并在常量表达式中对其调用 constexpr 成员函数。
不能在那里使用像 array<std::string, N>
这样的东西,因为 std::string
不是文字类型,所以 array<string, N>
.
也不是
Is there a cleaner way to achieve the static assertion?
标准特征 std::tuple_size
专用于 std::array
,因此您可以:
static_assert( std::tuple_size<decltype(some_array)>::value % 256) == 0,
"Size must be multiple of 256" );
我想明确说明成员变量的数组大小限制,以防止其他人不小心做出愚蠢的更改。以下天真的尝试将无法编译:
struct Foo
{
std::array< int, 1024 > some_array;
static_assert( (some_array.size() % 256) == 0, "Size must be multiple of 256" );
//^ (clang) error: invalid use of non-static data member 'some_array'
};
即使 std::array::size
是一个 constexpr,我也不能像那样直接使用 static_assert
,因为函数和我的成员变量都不是静态的。
我想到的解决方案是使用 decltype
(因为我不想对数组进行类型定义),如下所示:
static_assert( (decltype(some_array)().size() % 256) == 0, "Size must be multiple of 256" );
这看起来像是在默认构造一个 rvalue,我认为它不是 constexpr。
为什么这样做?
是否有更简洁的方法来实现静态断言?
std::array::size
是 constexpr
并且应该与 static_assert
一起工作,但是它在这个特定的上下文中不起作用(即在 class 定义中)因为 some_array
是一个非静态成员变量。
对于这个特定的上下文,您可以使用自制的类型特征在编译时获取大小,如下所示:
template<typename>
struct array_size;
template<typename T, std::size_t N>
struct array_size<std::array<T, N>> {
static const std::size_t size = N;
};
和static_assert
为:
static_assert(array_size<decltype(some_array)>::size % 256) == 0, "Size must be multiple of 256" );
because neither the function nor my member variable is static.
对。问题是静态断言不能引用非静态成员,因为 some_array.size()
等同于 this->some_array.size()
并且 class 范围内没有 this
指针(仅在函数声明符和默认成员初始值设定项内部)。
但是,说 decltype(array_size)
是可以的,因为这实际上并不是要引用对象 array_size
或调用它的成员函数,它只是查询在中声明的名称的类型class.
This looks like it's default-constructing an rvalue, which I didn't think is a constexpr.
array<int, N>
是字面量类型,所以可以用常量表达式构造。您正在构造一个右值这一事实并不重要,您可以构造一个文字类型并在常量表达式中对其调用 constexpr 成员函数。
不能在那里使用像 array<std::string, N>
这样的东西,因为 std::string
不是文字类型,所以 array<string, N>
.
Is there a cleaner way to achieve the static assertion?
标准特征 std::tuple_size
专用于 std::array
,因此您可以:
static_assert( std::tuple_size<decltype(some_array)>::value % 256) == 0,
"Size must be multiple of 256" );