Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a constexpr variable as dimension for declaring an (built-in) array?

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.

like image 418
user3791991 Avatar asked Mar 19 '23 03:03

user3791991


2 Answers

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] = {};
like image 51
TemplateRex Avatar answered Apr 26 '23 22:04

TemplateRex


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;
like image 45
Shafik Yaghmour Avatar answered Apr 26 '23 23:04

Shafik Yaghmour