在cppreference(4)上,转换构造函数描述如下:
转换构造函数。构造一个包含替代类型
T_j
的变体,如果F(std::forward<T>(t))
中每个F(T_i)
的虚函数T_i
都有重载,则可以通过重载解析为表达式Types...
选择该变体。 1}}同时作用域,除了:
- 仅当声明
F(T_i)
对某些发明变量T_i x[] = { std::forward<T>(t) };
有效时,才考虑重载x
;- 如果
T_i
是(可能是简历合格的)bool
,则只有F(T_i)
也是std:remove_cvref_t<T>
时,才考虑使用bool
。
我对关于bool
的第二个要点特别感兴趣。在示例中说:
std::variant<std::string, bool> y("abc"); // OK, chooses string; bool is not a candidate
我现在已经使用clang 7.0.0(godbolt),gcc.8.2(godbolt)和VS2017测试了相同的代码。我想知道为什么包含的替代类型是bool(对于所有三个编译器)而不是cppreference描述的std :: string。这是所有三个编译器的标准库中的错误吗?
我还找到了以下文档:P0608R3。这是否意味着仅对cppreference列表进行了修改(两个要点),但还不是正式标准的一部分?
答案 0 :(得分:11)
P0608R3在圣地亚哥被采用。其措词已应用于工作草案-您可以在[variant.ctor]/12中看到新的措词。
作为这一变化的一部分,激励人心的例子:
variant<string, bool> x = "abc";
现在可以保存一个string
(在c ++ 20中),而它以前可以保存一个bool
(在c ++ 17中)。此示例的含义在标准版本之间有所不同。
仅标准库尚未实现此更改。最近非常。在libstdc++和libc++页面上,该列表均被列为不完整。但是正如您所看到的,还有许多C ++ 20功能尚未实现。好消息是,它仍然是2019年初,还有很多时间。
答案 1 :(得分:5)
每个版本的C ++标准都有错误。数百个。
C ++实现旨在发挥作用,因此它们不会刻意遵守已发布的标准文本。没必要用一张纸来保持逐个错误的兼容性。
(作为一个极端的例子,直到C ++ 17技术上需要的标准的<int>
在std::vector<int> v;
将被解析为一个头名然后拒绝,因为它是不是#include
伪指令中,它应该不用说的没有的编译器会做到这一点。)
Cppreference也旨在发挥作用。因此,我们也不会保持与标准的逐项兼容。当最初在ISO发表的一篇论文中出现一段文字没有用时(也许除了标准的历史学家以外);作为程序员,我们关心的是使用-std=c++17
时得到的东西,或者实现的等效标志是什么。因此,我们的文档旨在对每个C ++标准进行假设性的完整正确实施,以及适用于该标准的所有后续错误修正和说明。 * 我们使用当前的实现作为此类假设性实现的证据。会做。
当存在的没有的当前实现特定的变化,我们评估变更的性质来预测的实现将如何处理它。核心语言的变化意在追溯标记为缺陷报告,使通话更容易(虽然有时他们没有达到所有回来的路上,和是的不在标签)。但是,更改库时并没有始终应用“ DR”标签,因此,这项工作完全取决于我们。
在该特定情况下,虽然P0608没有被标记为缺陷的报告,它出版后不久校正C ++ 17的极其可疑行为。此外,它是像代码非常不希望的std::variant<std::string, bool> x = "abcd";
,以默默变化意义的上相同的实现根据标准模式。代码依靠std::variant
也是在野外罕见的(这就是为什么部分委员会批准,即使摆在首位的“破”的变化)。结果,我预测该论文最终将被追溯应用并据此进行记录。
* 这是几年前哲学上的改变;结果,在很多情况下,错误修正在文档中并未被视为具有追溯力,而应在其中。随着时间的流逝,它们正在慢慢清理。