constexpr上下文中std :: array指针的size()

rab*_*exc 11 c++ gcc constant-expression c++11 clang++

假设我的功能如下:

int test(std::array<char, 8>* data) {
  char buffer[data->size() * 2];

  [... some code ...]
}
Run Code Online (Sandbox Code Playgroud)

显然,可以在编译时评估缓冲区的大小:数据有一个 constexpr大小为8个元素,8*2 = 16个字节.

然而,编译时-Wall,-pedantic-std=c++11我得到的臭名昭著的错误:

警告:可变长度数组是C99功能[-Wvla-extension]

我相信它是有道理的:array::size()constexpr,但它仍然是一种方法,在上面的函数中我们仍然必须取消引用指针,而不是constexpr.

如果我尝试类似的东西:

int test(std::array<char, 8>& data) {
  char buffer[data.size() * 2];
  [...]
}
Run Code Online (Sandbox Code Playgroud)

gcc (尝试过5.2.0版)似乎很高兴:没有警告.

但是对于clang++(3.5.1),我仍然会收到一个抱怨可变长度数组的警告.

在我的情况下,我不能轻易改变签名test,它必须采取指针.那么......几个问题:

  1. 在constexpr上下文中获取std::array 指针大小的最佳/最标准方法是什么?

  2. 预期指针与引用的行为有何不同?哪个编译器对警告是正确的,gcc或者clang

Yak*_*ont 2

我不知道2。

但对于 1,我们可以这样做:

template<class T, size_t N>
constexpr std::integral_constant<size_t, N> array_size( std::array<T, N> const& ) {
  return {};
}
Run Code Online (Sandbox Code Playgroud)

然后:

void test(std::array<char, 8>* data) {
  using size=decltype(array_size(*data));
  char buffer[size{}];
  (void)buffer;
  // [... some code ...]
}
Run Code Online (Sandbox Code Playgroud)

或者:

template<class T, class U, size_t N>
std::array<T,N> same_sized_array( std::array< U, N > const& ) {
  return {};
}

void test(std::array<char, 8>* data) {
  auto buffer = same_sized_array<char>(*data);
  (void)buffer;
  // [... some code ...]
}
Run Code Online (Sandbox Code Playgroud)

最后,C++14 清理:

template<class A>
constexpr const decltype(array_size( std::declval<A>() )) array_size_v = {};

void test3(std::array<char, 8>* data) {
  char buffer[array_size_v<decltype(*data)>];
  (void)buffer;
  // [... some code ...]
}
Run Code Online (Sandbox Code Playgroud)

活生生的例子