简体   繁体   中英

Returning nullptr for unique_ptr with custom deleter fails

When I attempt to compile this code it fails saying: " error: static assertion failed: constructed with null function pointer deleter". The line that it's complaining about is the "return nullptr". Returning nullptr works with other functions I've written which return a unique_ptr. Why is this so different and fails to even compile?

#include <iostream>
#include <memory>

template<typename ArrayType>
void deleter(ArrayType* array) noexcept
{
    if (array)
    {
        delete[] array;
        array = nullptr;
        std::cout << "Freed array." << std::endl;
    }
}
template<typename ArrayType>
std::unique_ptr<ArrayType[], decltype(&deleter<ArrayType>)> makeArray(const std::size_t size)
{
    return std::unique_ptr<ArrayType[], decltype(&deleter<ArrayType>)>{
        new ArrayType[size],
        deleter<ArrayType>
    };
}

std::unique_ptr<int[], decltype(&deleter<int>)> createInt(int s)
{
    if (s == 3)
        return makeArray<int>(3);
    else
        return nullptr;
}

void testArr(int arr[])
{
    if (arr != nullptr)
    {
        arr[0] = 1;
        arr[1] = 2;
        arr[2] = 3;
        std::cout << "Value 2 is " << arr[1] << std::endl;
    }
    else
        std::cout << "Array is empty." << std::endl;
}

int main() {
    auto arr0{createInt(4)}, arr1{createInt(3)};
    std::cout << "\tTesting arr0:\n";
    testArr(arr0.get());
    std::cout << "\tTesting arr1:\n";
    testArr(arr1.get());
    std::cout << "\tFinished testing\n";
    return 0;
}

It appears you need to use a function object, like:

template<typename ArrayType>
struct deleter {
    void operator()(ArrayType* array) {
    if (array)
    {
        delete[] array;
        array = nullptr;
        std::cout << "Freed array." << std::endl;
    }
    }
};

see here example:

http://coliru.stacked-crooked.com/a/172693cdc5704531

I think the relevant part from standard is in 20.8.1.2.1 [unique.ptr.single.ctor]

returning nullptr you call : unique_ptr& operator=(nullptr_t) noexcept; which calls constexpr unique_ptr() noexcept; , which in turn has in remarks:

Remarks: If this constructor is instantiated with a pointer type or reference type for the template argument D, the program is ill-formed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM