std::unique_ptr<T[]>::reset 在 gcc 6 中的实现

Implementation of std::unique_ptr<T[]>::reset in gcc 6

从 C++ 中的 GCC 6 开始,unique_ptr<T[]>::reset 方法(不是那个只接受 nullptr_t 的方法)的 declaration/definition 看起来像这样:

template <typename _Up,
            typename = _Require<
              __or_<is_same<_Up, pointer>,
                    __and_<is_same<pointer, element_type*>,
                           is_pointer<_Up>,
                           is_convertible<
                             typename remove_pointer<_Up>::type(*)[],
                             element_type(*)[]
                           >
                    >
              >
           >>
  void
  reset(_Up __p) noexcept
  {
using std::swap;
swap(std::get<0>(_M_t), __p);
if (__p != nullptr)
  get_deleter()(__p);
  }

为了实现 N4089,这在某些时候进行了更改。根据该文件:

This function behaves the same as the reset member of the primary template, except that it shall not participate in overload resolution unless either

U is the same type as pointer, or

pointer is the same type as element_type*, U is a pointer type V*, and V(*)[] is convertible to element_type(*)[].

让我们考虑以下示例:

std::unique_ptr<const char []> ptr1;
std::unique_ptr<char []> ptr2(new char[5]);
ptr1 = std::move(ptr2);

自版本 6 GCC 产生错误,抱怨它不能用 const char*&char*& 调用 std::swapreset 方法发生在重载决议中,因为 char[] 可转换为 const char[],但自然 std::swap 等待两个相同类型的引用。

这被认为是正确的行为吗?如果是这样,那为什么呢?如果我可以将 char[] 隐式转换为 const char[],为什么 unique_ptr 不能实现同样的效果?

所以这似乎真的是 gcc libstdc++ 中的一个错误。 @Barry 已报告:77987