【发布时间】:2018-05-18 01:56:47
【问题描述】:
MSVC 2017 社区 -std=c++17 阻塞了以下示例:
#include <iostream>
struct TC
{
static TC const values[];
static TC const& A;
static TC const& B;
static TC const& C;
int const _value;
};
inline constexpr TC const TC::values[]{ { 42 }, { 43 }, { 44 } };
inline constexpr TC const& TC::A{ values[0U] };
inline constexpr TC const& TC::B{ values[1U] };
inline constexpr TC const& TC::C{ values[2U] };
int main(int, char**) noexcept
{
std::cout << std::boolalpha
<< "&A == &values[0]? " << (&TC::A == &TC::values[0U]) << "\n"
<< "&B == &values[1]? " << (&TC::B == &TC::values[1U]) << "\n"
<< "&C == &values[2]? " << (&TC::C == &TC::values[2U]) << "\n";
return 0;
}
预期的输出是:
&A == &values[0]? true
&B == &values[1]? true
&C == &values[2]? true
gcc 和 clang 都产生了,但 MSVC 给出了:
&A == &values[0]? true
&B == &values[1]? false
&C == &values[2]? false
如果_value 成员被删除并且没有用户定义的构造函数,MSVC 会给出正确的结果。
由于所有这些都在一个翻译单元中,我的理解是这属于Partially-ordered dynamic initialization:
2) 部分有序的动态初始化,适用于所有 不是隐式或显式实例化的内联变量 专业化。如果在有序或之前定义了一个部分有序的 V 每个翻译单元中的部分有序 W,V 的初始化 在 W 的初始化之前排序(或者发生在之前,如果 程序启动一个线程)
我无法使用函数来确保初始化顺序,因为我需要 constexpr 值 和 constexpr 对它们的引用。
所以问题是,MSVC 在这里违反了标准*,对吗?
*当然cppreference.com 不是“标准”,但我假设那里的信息来源正确。
【问题讨论】:
-
从什么时候开始可以合法地将一个对象声明为非 constexpr 然后将其定义为 constexpr..?
-
听起来像是要提交给 MS 的反馈(在 VS 的帮助菜单下 -> 提交反馈)或者 developercommunity.visualstudio.com/spaces/62/index.html(它曾经是 connect.microsoft.com,但显然已经停止了)。
-
@ildjarn 我在标准中看不到任何禁止这种用法的内容
-
@ildjarn Richard Smith cites the standard - “7.1.5/1 说'
constexpr说明符应仅应用于变量的定义......'”所以constexpr(显然)是声明中不需要。 -
@monkey_05_06 在该引用的“...”中,它继续列出可以应用
constexpr的其他地方,例如声明。这句话也来自 C++11。
标签: c++ visual-c++ reference constexpr static-initialization