Jabor
Jabor

Reputation: 105

Unique Pointer as default parameter

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

Answers (3)

Galik
Galik

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

R Sahu
R Sahu

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

Rudolfs Bundulis
Rudolfs Bundulis

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

Related Questions