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?
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 typeconst E
. [Note: A pair of pointers or a pointer plus a length would be obvious representations forinitializer_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 ofinitializer_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.
Try setting Conformance mode on, and it will eliminate the compilation errors.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.