Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pass constexpr intializer_list as argument in c++14

Tags:

c++

c++11

c++14

Why doesn't this work:

constexpr initializer_list<int> ilist = {1,2,3,4};
constexpr int my_min = min(ilist);

While this does:

constexpr int my_min = min({1,2,3,4});

I'm basing my code on the constexpr std::min() function as shown here and I'm using clang3.5.0 to compiler (g++4.9.1 doesn't seem to be aware of a constexpr std::min()).

I can't make sense of the error I'm getting:

clang35 -stdlib=libc++ -std=c++14 test.cpp  -o test;
test.cpp:158:35: error: constexpr variable 'ilist' must be initialized by a constant expression
  constexpr initializer_list<int> ilist = {1,2,3,4};
                                  ^       ~~~~~~~~~
test.cpp:158:35: note: pointer to subobject of temporary is not a constant expression
test.cpp:158:43: note: temporary created here
  constexpr initializer_list<int> ilist = {1,2,3,4};
                                          ^
test.cpp:159:17: error: constexpr variable 'my_min' must be initialized by a constant expression
  constexpr int my_min = min(ilist);
                ^        ~~~~~~~~~~
test.cpp:159:30: note: initializer of 'ilist' is not a constant expression
  constexpr int my_min = min(ilist);
                             ^
test.cpp:159:30: note: in call to 'initializer_list(ilist)'
test.cpp:158:35: note: declared here
  constexpr initializer_list<int> ilist = {1,2,3,4};
like image 574
dcmm88 Avatar asked Jan 07 '15 20:01

dcmm88


1 Answers

The reason why your first snippet doesn't compile as opposed to the second one is the point in time at which the underlying array is being created. [dcl.init.list]/5:

An object of type std::initializer_list<E> is constructed from an initializer list as if the implementation allocated a temporary array of N elements of type const E, where N is the number of elements in the initializer list.

Now, when calling min, we access elements of that array. However, [expr.const]/7 is inviolable:

enter image description here

None of the exceptions apply, but note the last bullet point which is applicable in your second example.

Clang is (unsurprisingly) correct, while GCC spuriously accepts your code. The above ruling is also why @dyp's code fails: Performing an l-t-r conversion on i is not a constant expression. In particular, (2.7.1) doesn't apply since the temporary isn't const.

like image 190
Columbo Avatar answered Nov 02 '22 04:11

Columbo