首页 > 解决方案 > 为什么 std::optional::operator=(U&&) 要求 U 是非标量类型?

问题描述

对于可选的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

标签: c++language-lawyerc++17optional

解决方案


这是为了支持:

optional<int> o(42);
o = {}; // <== we want this to reset o

我们有一堆赋值重载,它们需要:

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

具体来说,对于标量,#4 将是标准转换,而其他任何东西都将是用户定义的转换 - 所以它将是最佳匹配。但是,这样做的结果将是赋值o0. 这意味着这o = {}可能意味着不同的事情,具体取决于T. 因此,我们排除了标量。

对于非标量,#4 和#3 将是等价的(都是用户定义的转换),而#3 将通过成为非模板而获胜。那里没问题。


推荐阅读