如何 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::sizeconstexpr 并且应该与 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" );

Live Demo

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" );