Avoiding the Tedium of Optional Parameters

avoiding the tedium of optional parameters

You might be interested in the Named Parameter Idiom.

To summarize, create a class that holds the values you want to pass to your constructor(s). Add a method to set each of those values, and have each method do a return *this; at the end. Have a constructor in your class that takes a const reference to this new class. This can be used like so:

class Person;

class PersonOptions
{
friend class Person;
string name_;
int age_;
char gender_;

public:
PersonOptions() :
age_(0),
gender_('U')
{}

PersonOptions& name(const string& n) { name_ = n; return *this; }
PersonOptions& age(int a) { age_ = a; return *this; }
PersonOptions& gender(char g) { gender_ = g; return *this; }
};

class Person
{
string name_;
int age_;
char gender_;

public:
Person(const PersonOptions& opts) :
name_(opts.name_),
age_(opts.age_),
gender_(opts.gender_)
{}
};
Person p = PersonOptions().name("George").age(57).gender('M');

C++ default arguments out of order?

It is not possible to invoke a function in the manner you suggested in C++. You can emulate named parameters via metaprogramming or simply pass a struct to your function. E.g.

struct options
{
bool option0{false};
bool option1{false};
bool option2{false};
};

void f(options opts = {});

C++11 usage:

options opts;
opts.option2 = true;
f(opts);

C++2a usage:

f({.option2=true});

Constructor with optional parameters

For this case, just give pathmode a default too

class LineEditPath : public QLineEdit
{
...
explicit LineEditPath(PathMode pathMode = default_or_sentinel_value, QWidget *parent = nullptr);
...
}

And remove the other constructor. Now the difference between default and sentinel value here would be, that default value you will just use, and not care if it was supplied by the user or by the compiler as default. This is probably what you want here, I suppose.

Sentinel value would be special value such as some "null" value, which can't be used like other values. You would have something like if(pathMode.isNull()) {...handle special case...} else {...use pathMode...} to handle it correctly.

For a more complex case, you might want to look at delegating constructors (link copied from comment of François Andrieux).

Would using optional parameters in a repository interface be considered bad design?

I've decided to use both parameters as properties on the repository itself. Taking into consideration the fact that the default value will be compiled into the caller, but also the fact that writing these parameters on every method on every possible repository could be tedious.

missing expression in a constructor

It seems you misunderstand how default arguments works in C++...

You can't skip arguments and have them be the default value. If you want to provide a later argument then you need to provide all arguments in front of it.

Therefore BandMember(nameNewMember, ageNewMember,,musicTypeNewMember) with the double-comma is not correct, you must provide the relationshipStatusToAdd argument as well:

return new BandMember(nameNewMember, ageNewMember,0,musicTypeNewMember);
// ^
// Added argument here --------------------------/

How can method overloading be avoided?

in C# 4, there are named parameters see Named and Optional Arguments (C# Programming Guide)

which would result in

new Foo(a: 1, d: 7, f: 6);

Another solution wwould be to define a Constructor with your defaut value ans use Object Initializer to set the values How to: Initialize Objects by Using an Object Initializer (C# Programming Guide)

new Foo()
{
a = 1,
d = 7,
f = 6
};

C++ function argument safety

A typical solution is to put the parameters in a structure, with named fields.

AllocateParams p;
p.num_buffers = 1;
p.pages_per_buffer = 10;
p.default_value = 93;
allocate_things(p);

You don't have to use fields, of course. You can use member functions or whatever you like.



Related Topics



Leave a reply



Submit