Reputation: 105
I am trying to give the nullpointer wrapped as a unique pointer as the default argument to a function. Using only pointers the header might look like this
double f(A* vec = nullptr);
Since I do however need to use a unique_ptr, I tried to change it to
double f(std::unique_ptr<A>& A vec = nullptr);
or
double f(std::unique_ptr<A>& A vec = std::unique_ptr<A>(nullptr));
Which results in the errors
could not convert ‘nullptr’ from ‘std::nullptr_t’ to ‘std::unique_ptr&’
and
cannot bind non-const lvalue reference of type ‘std::unique_ptr&’ to an rvalue of type ‘std::unique_ptr’
respecively. Is there a way to do this? I am relatively new to C++, so the answer might be obvious.
Not relevant to the question, but an explanation for my choice of unique_ptr: The parameter vec is used as the start value for an iteration in f and an improved value is returned with the pointer. The plan was that if no start value is given the pointer is set to the nullptr and a start value is calculated during the program. Since I however generate a new object, it would from all I can see be safer to use unique_ptr over a naked pointer.
Upvotes: 4
Views: 3544
Reputation: 48605
I would say you have two optione here.
1) The function does not own the pointer it merely uses it. In this case pass a raw pointer or (better) a reference (if nullptr is not an option).
// correct way to express a call to a non-owning function.
double f(A* vec = nullptr);
Calling code will use the function like this:
std::unique_ptr<A> vec;
f(vec.get()); // pass the raw pointer to the function
2) The function needs to manage the life of the pointer or reseat the pointer (own it) in which case accept a std::unique_ptr
by value.
// way to express transfer of ownership to a function
double f(std::unique_ptr<A> vec = std::unique_ptr<A>());
There is really no need to accept a reference if the function needs to take ownership of the pointer.
In discussions a third option has presented itself.
3) The function is expected to modify the pointer if you pass one in otherwise it will use its own internal pointer.
This is unusual but you could do this with a pair of overloaded functions like this:
// way to express a function that modifies a smart pointer
// (for example reseating it)
double f(std::unique_ptr<A>& vec);
// version where the uses doesn't want to supply the pointer
// and doesn't care about the modified value.
double f()
{
std::unique_ptr<A> vec; // a dummy
f(vec); // pass in the dummy
}
Upvotes: 8
Reputation: 206567
double f(std::unique_ptr<A>& vec = nullptr);
doesn't work since the compiler has to create a temporary std::unique_ptr
from nullptr
. Had you used
double f(std::unique_ptr<A> const& vec = nullptr);
the compiler would have accepted it.
One work around is to overload.
double f(std::unique_ptr<A>& vec)
{
return 0;
}
double f()
{
std::unique_ptr<A> vec = nullptr;
return f(vec);
}
Upvotes: 3
Reputation: 11934
The second error is because you are binding a non-const reference to a rvalue (which it kind of says). If that is a must, you cannot use a default value, or use a const reference:
double f(const std::unique_ptr<A>& A vec = std::unique_ptr<A>(nullptr));
Upvotes: 3