c++c++11gccunique-ptrgcc6

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


Since GCC 6 in C++ the declaration/definition of a unique_ptr<T[]>::reset method (not the one, that accepts only nullptr_t) looks like this:

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);
  }

This was changed at some point to implement N4089. According to that document:

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(*)[].

Let's consider the following example:

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

Since version 6 GCC produces an error, complaining that it cannot call std::swap with const char*& and char*&. reset method takes place in the overload resolution as char[] is convertible to const char[], but naturally std::swap awaits two references of the same type.

Is this considered to be a correct behavior? If so, then why? If I can implicitly convert char[] to const char[], why the same should not be possible with unique_ptr?


Solution

  • So this really seems to be a bug in gcc libstdc++. @Barry has reported it: 77987