Consider a method that takes a number of optional parameters. Such a method is often a code smell, but there are times when it is the best of several ugly options.

As I’ve written about before, Ruby 2’s keyword arguments or options Hash pattern provide an affordance that solves this problem nicely.

Let’s say we’re building a simple API for generating HTML content. We might have a method for creating a <div> element. <div> elements can have a number of attributes, but they are all optional.

With Ruby keyword arguments, we might do this:

Ruby div method
def div(klass: nil, id: nil, style: nil, hidden: false)
# ... code to generate the <div> element using the options ...
end

We can easily specify <div> elements with only a subset of the options, and we can specify them in any order.

Ruby div usage
div
div(id: "main")
div(hidden: true, class: "container")

In C++, the only affordance we have is to use positional parameters with default values.

Unsatisfying C++ div method
std::string div(const std::string& klass = "",
const std::string& id = "",
const std::string& style = "",
bool hidden = false)
{
// ... code to generate the <div> element using the parameters ...
}

This works. But the problem is that, in order to override a later option, we must also provide all earlier options which means knowing their default values. Also, we must provide the options in the order specified. And, when we look at a method call, we need to try to figure out what all of the arguments mean.

Unsatisfying C++ div usage
div();
div("", "main");
div("container", "", "", true);

We can try to optimize the parameter order such that the most commonly overridden parameters come first, but there’s not really any good way to win.

A Better Way

I was recently faced with this issue in an API I was designing, and I came up with a different solution.

I introduced a DivOptions struct with a fluent interface.

DivOptions
struct DivOptions
{
DivOptions() :
hidden_(false)
{
}
DivOptions& klass(const std::string& value)
{
klass_ = value;
return *this;
}
DivOptions& id(const std::string& value)
{
id_ = value;
return *this;
}
DivOptions& style(const std::string& value)
{
style_ = value;
return *this;
}
DivOptions& hidden(bool value)
{
hidden_ = value;
return *this;
}
std::string klass_;
std::string id_;
std::string style_;
bool hidden_;
};
std::string div(const DivOptions& options)
{
// ... code to generate the <div> element using options ...
}

I’m not fond of the trailing underscore naming convention here; I’d try to come up with better instance variable names. I might also make the instance variables private and add getter methods to access them. This struct is pretty localized and only used internally by the div() method, so I’m not too worried about that level of encapsulation.

Here’s how to use DivOptions:

Using C++ DivOptions
div();
div(DivOptions().id("main"));
div(DivOptions().hidden(true).klass("container"));

It’s not quite as direct as the Ruby keyword version, but it has a lot of the same advantages. I only need to provide the arguments I want to override. I can provide them in any order. And the method names communicate which argument is which.

The one downside is that I now have to go look at the DivOptions constructor to figure out what the default parameter values are; I can’t see them in the declaration of the div() method any more.

Next time you need to build a C++ API with a lot of optional parameters, consider using this pattern and let me know how it works out for you.