Начиная с GCC 6 в C ++ объявление / определение unique_ptr<T[]>::reset
метод (не тот, который принимает только nullptr_t
) выглядит так:
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. Согласно этому документу:
Эта функция ведет себя так же, как элемент сброса основного шаблона, за исключением того, что она
не должны участвовать в разрешении перегрузки, если только—
U
тот же тип, что иpointer
, или же—
pointer
тот же тип, что иelement_type*
,U
это тип указателяV*
, а такжеV(*)[]
конвертируется вelement_type(*)[]
,
Давайте рассмотрим следующий пример:
std::unique_ptr<const char []> ptr1;
std::unique_ptr<char []> ptr2(new char[5]);
ptr1 = std::move(ptr2);
Поскольку версия 6 GCC выдает ошибку, жалуясь, что не может вызвать std::swap
с const char*&
а также char*&
,
reset
Метод имеет место в разрешении перегрузки как char[]
конвертируется в const char[]
но естественно std::swap
ждет две ссылки одного и того же типа.
Считается ли это правильным поведением? Если так, то почему? Если я могу неявно преобразовать char[]
в const char[]
почему то же самое не должно быть возможно с unique_ptr
?
Так что это действительно ошибка в gcc libstdc ++.
@ Барри сообщил об этом: 77987
Других решений пока нет …