How does the standard define the capture of runtime-bound array?

Viewed 495

Please consider this code:

#include <iostream>
#include <algorithm>
#include <numeric>

int main()
{
    volatile auto width = uint64_t(5);

    alignas(16)
    char runtime[width]; std::iota(runtime,runtime+width,'1');

    auto out = [](auto& curr) { std::cout << curr; };

    auto capt_ref_to_runtime_bound_arr = [&runtime,width,out](auto &curr) { 
                                             std::for_each(runtime, runtime+width, out); 
                                             std::cout << " and width=" 
                                                       << sizeof(runtime) / sizeof(*runtime)
                                                       << '\n'; 
                                         };

    // clang code crashes even if below is commented out.
    // std::for_each(runtime,runtime+width,capt_ref_to_runtime_bound_arr);
}

about the [&runtime] capture

  1. GCC seems to decay int(&)[width] to char * (see wandbox below)

  2. clang just crashes into a red text chunk (see wandbox below)

Later, I ran to N3639, it says some features are cut off (e.g. sizeof in the demo above is actually ill-form). But why don't compilers explain these cut offs to me? And if the standard allow this kind of capture, how does they define it?


ASM: godbolt.org/g/ptRRRp

GCC 7.2 -O1: wandbox.org/permlink/30muSDtbxZYeGV2p

clang 5.0 -O1: wandbox.org/permlink/yvvRhBLFXzzxmihi

3 Answers

C++ standard (Bjarne Stroustrup) :

The number of elements of the array, the array bound, must be a constant expression (§C.5). If you need variable bounds, use a vector(§3.7.1, §16.3). For example:

void f(int i)
{
  int v1[i] ; / / error: array size not a constant expression
  vector<int> v2(i) ; / / ok
}

So, In all current and past C++ standards, that code is ill-formed. Variable Length Arrays are a C99 feature not a C++ feature.

Variable-length arrays in C++ are a GNU extension. There used to be some plans to add them to the language (in a more restricted fashion than the GNU extension). One of the challenges is that the C++ type system assumes that types have constant size and are fully laid out at compile time (otherwise, template metaprogramming would not work as it does today).

In previous GCC versions, it was sometimes possible to use variably modified types in templates, but this should have been fixed.

Related