Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why cannot I delete unique_ptr<char[]> with reset()?

When I have an unique pointer to a single object, I can delete it with reset():

std::unique_ptr<char> variable(new char);
variable.reset();

However, this does not work for an std::unique_ptr containing an array. Why? What is the proper way to delete such pointer?

I am using Embarcadero C++ Builder 10.1. and the relevant standard is C++11.

My observations

When I have an unique pointer containing an array, this fails to compile:

std::unique_ptr<char[]> variable(new char[10]);
variable.reset();

Error message is no matching function to call for 'reset'.

This also fails:

std::unique_ptr<char[]> variable(new char[10]);
variable.reset(nullptr);

Error messages are cannot initialize a variable of type 'pointer' (aka 'char *') with an lvalue of type '<bound member function type>' and assigning to '<bound member function type>' from incompatible type '_Null_ptr_type' (aka 'nullptr_t').

This compiles:

std::unique_ptr<char[]> variable(new char[10]);
variable = nullptr;

Relevant code from <memory>

template<class _Uty>
using _Enable_ctor_reset = enable_if_t<
    is_same<_Uty, pointer>::value
    || (is_same<pointer, element_type *>::value
    && is_pointer<_Uty>::value
    && is_convertible<
        remove_pointer_t<_Uty>(*)[],
        element_type(*)[]
    >::value)>;

_Myt& operator=(_Null_ptr_type) _NOEXCEPT
    {   // assign a null pointer
    reset(pointer());
    return (*this);
    }

_NOINLINE void reset(_Null_ptr_type _Ptr) _NOEXCEPT
    {   // establish new null pointer
    pointer _Old = this->_Myptr;
    this->_Myptr = _Ptr;
    if (_Old != pointer())
        this->get_deleter()(_Old);
    }

template<class _Uty,
    class = _Enable_ctor_reset<_Uty> >
void reset(_Uty _Ptr) _NOEXCEPT
    {   // establish new pointer
    pointer _Old = get();
    this->_Myptr() = _Ptr;
    if (_Old != pointer())
        this->get_deleter()(_Old);
    }
like image 348
VLL Avatar asked Nov 08 '22 07:11

VLL


1 Answers

It seems that this is a bug in the standard library, because the same code compiles with other compilers, as pointed out by deW1 and sanjay in comments.

C++11 standard, section 20.7.1.3 ("unique_ptr for array objects with a runtime length") lists reset() with the following signature:

void reset(pointer p = pointer()) noexcept;

The first example fails to compile, because the default argument is missing from the standard library implementation. The second example essentially calls reset(pointer()), which fails to compile. Possibly this compile error is the reason why the default argument has not been added.

I have made a bug report to Embarcadero:

RSP-16165 Compile error when calling reset() on unique_ptr containing array object

like image 121
VLL Avatar answered Nov 14 '22 21:11

VLL