4

I was imagining below scenario: start with an empty vector, push some int's to it, then use its size to declare an built-in array.

  vector<int> vec;      /* default init'ed */

  for(decltype(vec.size()) i = 0; i != 10; ++i){
    vec.push_back(i);
  }


  constexpr size_t sz = vec.size();
  int arr[sz] = {};     /* list init, left out elem's are 0 */

The procedure appears intuitive to me (as a beginner). But it fails with below message:

testconstexpr2.cpp:22:34: error: call to non-constexpr function ‘std::vector<_Tp, _Alloc>::size_type std::vector<_Tp, _Alloc>::size() const [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
testconstexpr2.cpp:23:13: error: size of array ‘arr’ is not an integral constant-expression

I would prefer sticking to built-in array before going to work-around such as std::array or dynamic array alloc.

user3791991
  • 129
  • 6

2 Answers2

5

This won't work because vec.size() is not a constexpr function and an array dimension has to be a compile-time constant expression.

During C++1y/C++14 development (not quite finished) there was a proposal called std::dynarray that would allow you to do this, but that was dropped and is perhaps to be relaunched during the next C++1z/C++17 development.

What you can do is

constexpr size_t sz = 10; /* or any other integral constant expression */
int arr[sz] = {};
TemplateRex
  • 69,038
  • 19
  • 164
  • 304
2

constexpr for a variable means it can be evaluated at compile time. A constexpr function can be evaluated at run-time or compile-time. The conditions a constexpr variable must satisfy are as follows (emphasis mine):

  • its type must be a LiteralType.
  • it must be immediately constructed or assigned a value.
  • the constructor parameters or the value to be assigned must contain only literal values, constexpr variables and functions.
  • the constructor used to construct the object (either implicit or explicit) must satisfy the requirements of constexpr constructor. In the case of explicit constructor, it must have constexpr specified.

which is consistent with the draft C++ standard section 7.1.5 The constexpr specifier paragraph 9.

std::vector::size is not a constexpr method and so this won't work. If you know the size before hand, which you seem to then you can declare the variable using the literal 10:

constexpr size_t sz = 10 ;

note that this is a case where you could have used const as well since it is being initialized with a literal:

const size_t sz = 10;
Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • "If you know the size before hand" applies to this case. On the other hand, if the size is unknown (e.g. using a `while` loop to take random number of `int`), is there a way to declare an built-in array with dimension matching that vector? (or maybe the best shot is to `malloc` a pointer?) – modeller Jul 03 '14 at 21:20
  • @user3701346 if it is not a [constant expression](http://en.cppreference.com/w/cpp/language/constant_expression) then it won't work. Since this is C++ `new` would be an alternative although it is not clear to me why `std::vector` does not work? Can you explain why you need an array? [gcc and clang support VLA as an extension](http://stackoverflow.com/a/21273849/1708801) but I would avoid that since it is not really idiomatic C++. – Shafik Yaghmour Jul 03 '14 at 21:28
  • I saw this on book exercise asking to copy from vector to array (built-in type). Its wording did not forbid an random sized vector so I asked about `while` case for completeness. – modeller Jul 03 '14 at 21:35