Ahmed A
Ahmed A

Reputation: 3662

Default value for a reference parameter to a function

I have a function that takes two parameters. The first parameter is an int& which the function will set to some "return" value. The second parameter is a pointer and is optional. The caller can pass a valid pointer if the caller wishes it to be initialized, and if not the default value is nullptr.

void find_lis(uint32_t& count,
              vector<uint32_t>* output = nullptr)
{ }

All is well. However, I want to make the second parameter a reference, and allow caller the same option to provide one or not, what should I use as the default value?

void find_lis(uint32_t& count,
              vector<uint32_t>& output = ???)
{ }

I tried a few things, but they cause a compiler error. However, the following at least compiles, but I am not sure if it is right?

void find_lis(uint32_t& count,
              vector<uint32_t>& output = *(new vector<uint32_t>()))
{ }

In the pointer case, I can easily check if the caller passed in a second parameter by comparing value to nullptr. However, in the reference case, I don't see any such easy check.

Upvotes: 2

Views: 3999

Answers (2)

R Sahu
R Sahu

Reputation: 206737

If the implementation of the function is not overly complex, I would suggest creating two overloaded functions.

void find_lis(uint32_t& count)
{
   count = 0; // ???
}

void find_lis(uint32_t& count,
              vector<uint32_t>& output)
{
   // Proper implementation
}

Another option:

void find_lis(uint32_t& count)
{
   // I'm guessing this will work. May be not.
   static vector<uint32_t> dummy;
   find_lis(count, dummy);
}

void find_lis(uint32_t& count,
              vector<uint32_t>& output)
{
   // Proper implementation
}

Update, in response to comment by OP

Use:

void find_lis_private(uint32_t& count,
                      vector<uint32_t>& output,
                      bool update)
{
   // Proper implementation
}

void find_lis(uint32_t& count)
{
   static vector<uint32_t> dummy;
   find_lis_private(count, dummy, false);
}

void find_lis(uint32_t& count,
              vector<uint32_t>& output)
{
   find_lis_private(count, output, true);
}

A better option is to use:

template <typename UpdateFunction>
void find_lis_private(uint32_t& count,
                      vector<uint32_t>& output,
                      UpdateFunction fun)
{
   // Proper implementation
   // call fun() with the necessary arguments when it's time
   // to update.
}

void find_lis(uint32_t& count)
{
   static vector<uint32_t> dummy;
   find_lis_private(count, dummy, [](args...) {/* Empty function */});
}

void find_lis(uint32_t& count,
              vector<uint32_t>& output)
{
   find_lis_private(count, output, [=output](args...) {/* Update output */});
}

Then, you don't have to use if/else blocks to update.

Upvotes: 4

Paul Groke
Paul Groke

Reputation: 6447

If you really want to bind a temporary to an lvalue reference, you can use a helper function to convert the rvalue to an lvalue:

template <class T>
T& lvalue_cast(T&& t)
{
    return t;
}

void find_lis(uint32_t& count,
              std::vector<uint32_t>& output = lvalue_cast(std::vector<uint32_t>()))
{
}

Upvotes: 2

Related Questions