How to pass NULL or nullptr to a function that receives a unique_ptr argument?

Viewed 455
template<typename T>
void foo(T&& p1)
{
    p1.get();
}

int main(int argc, char *argv[])
{
    auto a = std::unique_ptr<int>();
    a = NULL;
    
    // this works because a is a unique ptr and it has a get method
    foo(a);
    // this does not work because NULL does not has this method. But can it work tho like how we use the raw pointer?
    foo(NULL);
    return 0;
}

So basically I want to finish some function/API that can receive both nullptr literal and unique_ptr as funtion argument. How can I do it?

2 Answers

You might write overload for std::nullptr_t:

void foo(std::nullptr_t) {}

And SFINAE the first form to discard it for wrong type as int (possible type of NULL):

template<typename T>
auto foo(T&& p1) -> decltype(p1.get(), void())
{
    p1.get();
}

but use nullptr instead of NULL

If foo should accept a unique_ptr specifically, you can write:

template<typename ...T>
void foo(std::unique_ptr<T...>& p1)
{
    p1.get();
}

With regards to using a NULL argument, I suggest not doing that. It's a macro that may evaluate to the int literal 0, or a prvalue of type std::nullptr_t, and is no longer the preferred way of signaling a pointer that is not pointing at valid memory.

You should use nullptr instead, and then you can write an overload to match that:

void foo(std::nullptr_t) {}  

If you still want to use NULL or otherwise match any argument that is not a specialization of unique_ptr, you can add an overload that matches everything else:

void foo(...) {}  

Here's a demo.

Related