【问题标题】:Why do std::optional constructors use std::in_place?为什么 std::optional 构造函数使用 std::in_place?
【发布时间】:2018-09-20 22:01:42
【问题描述】:

一些std::optional 构造函数使用std::in_place_t 标记参数,如下所示:

template< class... Args > 
explicit optional( std::in_place_t, Args&&... args );

我看到这样的构造函数可以在没有就地标记的情况下实现,并使用一些enable_if (SFINAE) 魔法来不参与不情愿的重载,即:

template< class... Args > 
explicit optional( Args&&... args );

为什么std::optional 的就地构造函数使用std::in_place_t 标签而不是一些enable_if 魔术(并且没有标签)实现?

更新:稍微更新了问题,以强调我意识到简单地省略就地标记是行不通的。

【问题讨论】:

  • 匹配任何东西。
  • @Cheersandhth.-Alf 为什么这是个问题?
  • 假设T 有一个隐式转换构造函数,它接受一个类型不等于T 的单个参数。然后,您将创建一个临时值,而不是将该值用于就地构造,而没有机会更改它。
  • @MatthäusBrandl 但你可以通过 SFINAE 来阻止这种情况。实际上,无论有无标签,都只转发一个参数。没有创建临时对象
  • 据我所知,假设的无标签版本失败的唯一情况是默认构造包含的值

标签: c++ c++17 stdoptional


【解决方案1】:

正如Passer By 在comment 中所说,其目的是为了消除人们想要调用optional&lt;T&gt; 的默认构造函数和想要调用T 的默认构造函数的情况的歧义。

此意图在N3527 中提出,其中in_place_t 的原始建议名称为emplace。我在这里引用相关部分:

我们需要额外的标签来消除某些情况的歧义,比如调用optional的默认构造函数和请求T的默认构造函数:

optional<Big> ob{emplace, "1"}; // calls Big{"1"} in place (no moving)
optional<Big> oc{emplace};      // calls Big{} in place (no moving)
optional<Big> od{};             // creates a disengaged optional

【讨论】:

  • 如何搜索论文/提案?
  • @0x499602D2 我用关键字“C++ in_place_t paper”搜索,找到N3793,然后找到N3527。
  • @0x499602D2 如果您有权访问 CppLang Slack,您可以向 npaperbot 发送消息。真的很棒!
  • @xskxzr 如果 std::optional&lt;T&gt; 构造函数输入 2 个或更多参数,难道不能总是假设这些需要转发给 T's 构造函数,因此不需要 in_place_t 吗?
  • @user3882729 2 个或多个 args 的接口与 1 个 args 的接口不同,这很奇怪。
猜你喜欢
  • 2021-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-11
  • 2021-11-29
  • 2018-03-14
  • 1970-01-01
相关资源
最近更新 更多