使用 constexpr initializer_list 构造函数时 MSVC 无法编译
MSVC fails to compile when using a constexpr initializer_list constructor
为什么Microsoft Visual C++编译以下代码时会失败? :
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, "!!");
我得到的错误是:
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
initializer_list
的实现所有方法都标记为 constexpr
,看起来对我来说应该没问题...也许这只是一个编译器问题?
TL;DR:这是一个编译器标准问题,因为你的代码可以很好地编译 gcc 6.3.1 and clang 3.9.1 虽然都编译你的代码。
在 C++11 中,没有一个方法被标记为 constexpr
,因此您不能在 static_assert
. 中使用它
您必须注意 Visual Studio 2015 没有完整的 constexpr
支持。请参阅 C++ 14 核心语言功能
table 中的文章。它只实现了 std::initializer_list
的 C++11 版本,没有任何 constexpr
函数。
小更新:看起来标准中的错误措辞会导致非常数 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
.
(无耻地从 this 答案中复制。)它更深入一点,关于为什么你不能在 constexpr
上下文中使用 std::initializer_list
。
这已在 Visual Studio 2017 年“修复”。
尝试将 Conformance mode 设置为开,它会消除编译错误。
为什么Microsoft Visual C++编译以下代码时会失败? :
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, "!!");
我得到的错误是:
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
initializer_list
的实现所有方法都标记为 constexpr
,看起来对我来说应该没问题...也许这只是一个编译器问题?
TL;DR:这是一个编译器标准问题,因为你的代码可以很好地编译 gcc 6.3.1 and clang 3.9.1 虽然都编译你的代码。
在 C++11 中,没有一个方法被标记为 中使用它constexpr
,因此您不能在 static_assert
.
您必须注意 Visual Studio 2015 没有完整的 constexpr
支持。请参阅 C++ 14 核心语言功能
table 中的文章。它只实现了 std::initializer_list
的 C++11 版本,没有任何 constexpr
函数。
小更新:看起来标准中的错误措辞会导致非常数 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
.
(无耻地从 this 答案中复制。)它更深入一点,关于为什么你不能在 constexpr
上下文中使用 std::initializer_list
。
这已在 Visual Studio 2017 年“修复”。
尝试将 Conformance mode 设置为开,它会消除编译错误。