3

Why does Microsoft Visual C++ fails when compile the following code? :

template <typename T>
struct slice
{
    size_t length;
    T *ptr;

    constexpr slice(std::initializer_list<T> list)
        : length(list.size()), ptr(list.begin()) {}
};

static_assert(slice<const int>({ 1, 2, 3 }).length == 3, "!!");

The error I get is:

1>test.cpp(12): error C2131: expression did not evaluate to a constant
1>         visual studio 14.0\vc\include\initializer_list(50): note: failure was caused by an undefined arithmetic operation

The implementation of initializer_list has all methods marked constexpr, it looks like it should be fine to me... Maybe it's just a compiler issue?

2 Answers 2

8

TL;DR: It is a compiler Standard issue, as your code compiles fine with gcc 6.3.1 and clang 3.9.1 both compile your code though.


In C++11, not one of the methods is marked constexpr, and so you can't use it in a static_assert.

You have to note that Visual Studio 2015 doesn't have full constexpr support. See the C++ 14 Core Language Features table in the article. It has only the C++11 version of std::initializer_list implemented, which doesn't have any constexpr functions.

Small update: It looks like a bad wording in the standard can result in a non-constant std::initializer_list:

From § 18.9.2 (emphasis mine):

An object of type initializer_list<E> provides access to an array of objects of type const E. [Note: A pair of pointers or a pointer plus a length would be obvious representations for initializer_list. initializer_list is used to implement initializer lists as specified in 8.5.4. Copying an initializer list does not copy the underlying elements.
—end note]

So there is no requirement for the private members of the implementation of initializer_list to be non-volatile literal types; however, because they mention that they believe a pair of pointers or a pointer and a length would be the "obvious representation," they probably didn't consider that someone might put something non-literal in the members of initializer_list.

(Shamelessly copied from this answer.) It goes a bit more in depth, about why you couldn't use std::initializer_list in a constexpr context.

This has been "fixed" in Visual Studio 2017.

Sign up to request clarification or add additional context in comments.

6 Comments

My VS2015 <initializer_list> which it is compiling against does indeed have constexpr on all methods, that's why I was surprised it didn't work.
@ManuEvans That's weird. After investigation I found that the cause is a bad wording in the Standard, which seems to not have been fixed in the implementation of VS 2015. See edit :)
@Rakete1111 - confirmed. ' Compiles with VS2017
@Jeff Thanks for the info! :)
@Jeff That's funny, I tried to switch to 2017, but ran into a much bigger issue: stackoverflow.com/questions/42917099/…
|
0

Try setting Conformance mode on, and it will eliminate the compilation errors. enter image description here

1 Comment

Doesn't for me. However turning off SDL checks works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.