为什么std :: optional :: operator =(U &&)要求U是非标量类型?

Zel*_*lta 15 c++ optional language-lawyer c++17

对于可选项template<class U = T> optional<T>& operator=(U&& v);,标准要求(参见[optional.assign] /3.16):

除非... conjunction_v<is_scalar<T>, is_same<T, decay_t<U>>>false ... 否则此函数不应参与重载决策 .

为什么在分配类型标量时我们必须排除大小写U == T

Bar*_*rry 22

这是为了支持:

optional<int> o(42);
o = {}; // <== we want this to reset o
Run Code Online (Sandbox Code Playgroud)

我们有一堆赋值重载,它们采用:

  1. nullopt_t
  2. optional const&
  3. optional&&
  4. U&&
  5. optional<U> const&
  6. optional<U>&&

对于标量,具体而言,#4将是标准转换,而其他任何东西都是用户定义的转换 - 因此它将是最佳匹配.但是,其结果将是指定o使用值0.这意味着o = {}根据类型的不同,可能意味着不同的东西T.因此,我们排除了标量.

对于非标量,#4和#3将是等效的(两个用户定义的转换),#3将通过非模板获胜.没问题.