用bool转换C ++变体的构造函数

时间:2019-02-01 15:15:38

标签: c++ c++17 c++20

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列表进行了修改(两个要点),但还不是正式标准的一部分?

2 个答案:

答案 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也是在野外罕见的(这就是为什么部分委员会批准,即使摆在首位的“破”的变化)。结果,我预测该论文最终将被追溯应用并据此进行记录。


* 这是几年前哲学上的改变;结果,在很多情况下,错误修正在文档中并未被视为具有追溯力,而应在其中。随着时间的流逝,它们正在慢慢清理。