为什么在编译以下代码时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
,看起来它对我来说应该没问题......也许这只是编译器问题?
答案 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设置为开,这将消除编译错误。