如何static_assert std :: array成员的大小

时间:2016-02-04 22:28:34

标签: c++ c++11 clang static-assert stdarray

我想明确关于成员变量的数组大小限制,以阻止其他人意外地进行愚蠢的更改。以下天真尝试将无法编译:

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

为什么这样做?

是否有更简洁的方法来实现静态断言?​​

2 个答案:

答案 0 :(得分:7)

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

Live Demo

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