首页 > 解决方案 > std::optional 构造函数中 in_place_t 背后的动机

问题描述

我试图更好地理解构造函数背后in_place_t的动机。std::optional<T>我得到用例来消除使用默认构造函数构建null可选与类型的歧义。T但是,如果为std::optional构造函数指定了一个或多个参数,那么不能假设它们总是可以转发给构造函数T吗?

#include <optional>

struct X
{
   X(int, int) {}
};

int main()
{
   std::optional<X> op{std::in_place, 1,2};
   //std::optional<X> op{1,2}; Does not compile, but why can't it be assumed that 1,2 always go to the constructor of X 
}

标签: c++c++17stdoptional

解决方案


它归结为另一个模棱两可。一个例子:如果T可以从 构造,当从一个对象构造optional<T>时会发生什么?参数的期望行为是复制构造还是转发给构造函数?optional<T>optional<T>optional<T>T

这在N3527中得到了解决(我从一个相关问题的答案中获得了它的链接。)考虑了转发参数的可能性,但被驳回了。

但是,这种【完美转发】模型也存在一定的问题。首先,完美转发也有例外:标签nullopt不转发。此外,类型参数optional<T>不是。如果 T 有这样的构造函数,这变得可见:

struct MyType
{
  MyType(optional<MyType>, int = 0);
  // ... 
};

此外,一般情况下,由于涉及特殊的推导规则,不可能完美转发 initializer_list。

该论文还发现了完美转发下的默认构造问题。(默认构造optional<T>将包含一个 default-constructed而不是不包含值。)这部分可以通过要求标签构造一个包含 default-constructedT的标签来回避——以一定的一致性为代价。我认为这是较小的障碍,而歧义问题是主要的障碍。in_place_toptional<T>T


我想你可以继续问为什么不转发两个或更多参数(当第一个不是标签时)?在某些时候,一致性确实成为了一个理想的目标。保持界面简洁。如果将零个或一个参数转发给 的构造函数需要一个标签T,那么对于任意数量的参数都需要它。要记住的规则越少,编程错误就越少。


推荐阅读