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 aspointer
, orā
pointer
is the same type aselement_type*
,U
is a pointer typeV*
, andV(*)[]
is convertible toelement_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
?
So this really seems to be a bug in gcc libstdc++. @Barry has reported it: 77987