我想明确关于成员变量的数组大小限制,以阻止其他人意外地进行愚蠢的更改。以下天真尝试将无法编译:
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 。
为什么这样做?
是否有更简洁的方法来实现静态断言?
答案 0 :(得分:7)
std::array::size
是constexpr
并且应该与static_assert
一起使用,但它不适用于此特定上下文(即,在类定义中),因为some_array
是非-static成员变量。
对于这个特定的上下文,您可以使用自制类型特征在编译时获取大小,如下所示:
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" );
答案 1 :(得分:5)
因为函数和我的成员变量都不是静态的。
右。问题是静态断言不能引用非静态成员,因为some_array.size()
等同于this->some_array.size()
并且类范围内没有this
指针(仅在函数声明符内部)和默认成员初始化者。)
但是,可以说decltype(array_size)
因为实际上并没有尝试引用对象array_size
或者调用它的成员函数,它只是查询类中声明的名称的类型
这看起来像是默认构造一个右值,我认为它不是一个constexpr。
array<int, N>
是一个文字类型,因此可以用常量表达式构造。你构造一个rvalue的事实并不重要,你可以构造一个文字类型,并在一个常量表达式中调用constexpr成员函数。
array<std::string, N>
之类的内容无法在那里使用,因为std::string
不是文字类型,因此array<string, N>
也不是。{/ p>
是否有更简洁的方法来实现静态断言?
标准特征std::tuple_size
专门用于std::array
,因此您可以执行以下操作:
static_assert( std::tuple_size<decltype(some_array)>::value % 256) == 0,
"Size must be multiple of 256" );