使用constexpr initializer_list构造函数时,MSVC无法编译

时间:2017-03-20 06:18:48

标签: 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,看起来它对我来说应该没问题......也许这只是编译器问题?

2 个答案:

答案 0 :(得分:7)

TL; DR :这是一个编译器标准问题,,因为你的代码可以很好地编译 gcc 6.3.1和{{3两者都编译你的代码。

在C ++ 11中,没有一个方法标记为constexpr,因此您无法在static_assert中使用它。

您必须注意Visual Studio 2015没有完整的constexpr支持。请参阅文章中的clang 3.9.1表。它只实现了std::initializer_list的C ++ 11版本,它没有任何constexpr函数。

小更新:看起来标准中的错误措辞会导致非常数std::initializer_list

  

从§18.9.2(强调我的):

     

类型为initializer_list<E>的对象提供对const E类型对象数组的访问。 [注意:一对指针或指针加上长度将是initializer_list的明显表示。 initializer_list用于实现8.5.4中指定的初始化列表。复制初始化列表不会复制基础元素    - 后注]

     

因此,initializer_list的实现的私有成员不需要是非易失性的文字类型;然而,因为他们提到他们相信一对指针或一个指针和一个长度将是“明显的代表”,他们可能不会认为某人可能会在initializer_list的成员中放入非文字的东西。

(从the C++ 14 Core Language Features 回答无耻地复制。)它更深入一些,说明为什么你不能在std::initializer_list上下文中使用constexpr

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

答案 1 :(得分:3)

尝试将Conformance mode设置为开,这将消除编译错误。 enter image description here