c++ - 使用 constexpr initializer_list 构造函数时 MSVC 无法编译

标签 c++ c++11 visual-c++ constexpr initializer-list

为什么 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.1clang 3.9.1两者都编译你的代码。


在 C++11 中,没有一个方法被标记为 constexpr , 所以你不能在 static_assert 中使用它.

您必须注意 Visual Studio 2015 没有完整的 constexpr支持。参见 the C++ 14 Core Language Features 文章中的表格。它只有 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 答案中复制。)它更深入一点,关于为什么你不能使用 std::initializer_list。在constexpr上下文。

这已在 Visual Studio 2017 中“修复”。

关于c++ - 使用 constexpr initializer_list 构造函数时 MSVC 无法编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42896993/

相关文章:

c++ - 如何测试 shared_ptr 是空的还是什么都不拥有

c++ - C中相同字符子串的递归算法

c++ - 为什么这个 c++ 有效? (具有相同名称的变量)

c++ - 为什么在std::deque.erase()上引发异常?

c++ - 如何在 Visual C++ 中有条件地包含一个不存在的文件?

c++ - 使用 SFINAE 根据类模板参数的类型更改类中调用的函数

c++ - 为什么discard的参数是unsigned long long类型的?

c++ - 这个打印代码是如何工作的?

c++ - 如何使 Visual Studio C++ 2010 编译行为像 gcc/g++? (或相反亦然)

c++ - 将 Visual C++ 代码转换为 Borland C++Builder