Question

I'm trying to create a function in C++ which takes in 3 parameters, but the 3rd parameter I want to allow nothing to be passed.

Like for example How can I code this C# function

public void GatherMovements( bool xPositions, bool yPositions, bool zPositions = null )

how can I create this in C++? is there a way?

Was it helpful?

Solution

Default arguments are possible. The problem here is that a bool cannot have a null value. So there are a few possibilities for you. You can either give that argument a default value that is a valid bool:

void GatherMovements(bool xPositions, bool yPositions, bool zPositions = false);

Or you can have two overloads of the function - one that takes 3 arguments and one that takes 2:

void GatherMovements(bool xPositions, bool yPositions, bool zPositions);
void GatherMovements(bool xPositions, bool yPositions);

One function may call the other if they can be implemented in terms of each other.

The second approach is only necessary if calling the function with true, false, and no final parameter are fundamentally different operations.

If you really want only one function and the three cases should be considered different, then one final option for you is to use a boost::optional:

void GatherMovements(bool xPositions, bool yPositions, boost::optional<bool> zPositions);

However, I suggest that the overload approach is preferable (no dealing with extra unnecessary types).

OTHER TIPS

Default parameters need to be listed in the declaration (not definition). So, your declaration would be:

public:
 void GatherMovements(bool xPos, bool yPos, bool zPos = false);

and your definition would be:

void MyClass::GatherMovements(bool xPos, bool yPos, bool zPos /* = false */) {}

In addition, the default parameter needs to be passed by value here, i.e., you can't have:

public:
     void GatherMovements(bool xPos, bool yPos, bool& zPos = false);

Using boost or the C++1y proposed std::optional you can solve this.

void GatherMovements(bool xPos, bool yPos, boost::optional<bool> zPos = boost::nullopt);

in the body of GatherMovements, you can tell if zPos was passed by doing if(zPos). You can get the bool value of zPos by doing *zPos. In a sense, zPos follows C++ pointer semantics for dereferencing.

If you dereference zPos without checking to see if it is valid, you get undefined behavior.

It is easy to accidentally use zPos as a bool without dereferencing it by accident, so be careful.

Another option if you do not want to work with C++1y or boost would be to take a bool const*, and have an overload:

void GatherMovements_Internal(bool xPos, bool yPos, bool const* zPos);
void GatherMovements(bool xPos, bool yPos, bool zPos) { GatherMovements_Internal(xPos, yPos, &zPos); }
void GatherMovements(bool xPos, bool yPos) { GatherMovements_Internal(xPos, yPos, nullptr); }

now you write GatherMovements_Internal, and within it zPos is nullptr if it was not passed, and otherwise points to the bool that was passed. Note that the lifetime of this pointer is not guaranteed to last past the function call (so do not store the pointer).

Use the same logic as the optional case above (if (zPos) to find out if it exists, and *zPos to get the value out if it exists).

If using boost already / depending on it wouldn't be a problem, there's tribool::indeterminate_value which you could use as a default value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top