avoiding the tedium of optional parameters - c++

If I have a constructor with say 2 required parameters and 4 optional parameters, how can I avoid writing 16 constructors or even the 10 or so constructors I'd have to write if I used default parameters (which I don't like because it's poor self-documentation)? Are there any idioms or methods using templates I can use to make it less tedious? (And easier to maintain?)

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');

What if you made a parameter object that contained all the fields? Then you could just pass that, and just set whichever fields you need. There's probably a name for that pattern, not sure what it is though...
UPDATE:
Code might look like somewhat this:
paramObj.x=1;
paramObj.y=2;
paramObj.z=3;
paramObj.magic=true;
... //set many other "parameters here"
someObject myObject = new someObject(paramObj);
and inside the someObject constructor you can set defaults for things that were not already set (or raise an error if it was mandatory).
Honestly, I'm not a big fan of this solution, but I've used it once or twice when paramObj made sense by containing a set of data that usually all went together (so we could use it for more than just constructors), and it was better than multiple constructors. I found that it was ugly but it worked, YMMV.

And now for the "Boost has something for it" answer:
The Boost Parameter Library seems to be a good fit to your use case.

All new for C++17
#include <optional>
using optional_int = std::optional<int>;
class foo {
int arg0, arg1; // required
int arg2, arg3; // optional
const int default_2 = -2;
const int default_3 = -3;
public:
foo(int arg0, int arg1, optional_int opt0 = {}, optional_int opt1 = {})
: arg0(arg0), arg1(arg1)
, arg2(opt0.value_or(default_2))
, arg3(opt1.value_or(default_3))
{ }
};
int main() {
foo bar(42, 43, {}, 45); // Take default for opt0 (arg2)
return 0;
}
I have a cubic spline implementation that allows the user optionally to specify the first derivative at either the left end, the right end, or both. If a derivative is not specified, then the code in effect calculates one, by assuming that the second derivative is zero (the so-called "natural spline"). Here is a fragment for the left end.
// Calculate the second derivative at the left end point
if (!left_deriv.has_value()) {
ddy[0]=u[0]=0.0; // "Natural spline"
} else {
const real yP0 = left_deriv.value();
ddy[0] = -0.5;
u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yP0);
}

Related

Call an "initialize" function in an object when one of its member functions are called

I am trying to implement lazy initializing in C++ and I am searching for a nice way to call the Initialize() member function when some other method like object->GetName() gets called.
Right now I have implemented it as follows:
class Person
{
protected:
bool initialized = false;
std::string name;
void Initialize()
{
name = "My name!"; // do heavy reading from database
initialized = true;
}
public:
std::string GetName()
{
if (!initialized) {
Initialize();
}
return name;
}
};
This does exactly what I need for the time being. But it is very tedious to setup the initialized check for every method, so I want to get rid of that. If someone knows a nice way in C++ to improve this above example, I would like to know!
Could maybe operators be used to achieve calling Initialize() when using -> for example?
Thanks!
Sounds like a job for templates! Create a lazily_initialized wrapper that takes a type T and a function object TInitializer type:
template <typename T, typename TInitializer>
class lazily_initialized : TInitializer
{// ^^^^^^^^^^^^^^
// inheritance used for empty-base optimization
private:
T _data;
bool _initialized = false;
public:
lazily_initialized(TInitializer init = {})
: TInitializer(std::move(init))
{
}
T& get()
{
if(!_initialized)
{
static_cast<TInitializer&>(*this)(_data);
_initialized = true;
}
return _data;
}
};
You can the use it as follows:
struct ReadFromDatabase
{
void operator()(std::string& target) const
{
std::cout << "initializing...\n";
target = "hello!";
}
};
struct Foo
{
lazily_initialized<std::string, ReadFromDatabase> _str;
};
Example:
int main()
{
Foo foo;
foo._str.get(); // prints "initializing...", returns "hello!"
foo._str.get(); // returns "hello!"
}
example on wandbox
As Jarod42 mentioned in the comments, std::optional<T> or boost::optional<T> should be used instead of a separate bool field in order to represent the "uninitialized state". This allows non default-constructible types to be used with lazily_initialized, and also makes the code more elegant and safer.
As the former requires C++17 and the latter requires boost, I used a separate bool field to make my answer as simple as possible. A real implementation should consider using optional, using noexcept where appropriate, and also consider exposing a const-qualified get() that returns a const T&.
Maybe call it in the constructor?
Edit: Uh, i missed the point of your question sorry.
What about a lazy factory initialization?
https://en.wikipedia.org/wiki/Lazy_initialization#C.2B.2B

Setting the data member for a class derived from a class derived from std::string to a value

I am trying to figure out this assignment from my level 2 class.
We are to create a class called Number, derived from std::string.
the only code in this class is to be two constructors, a default and one that takes a string as an arguement.
I have:
class Number : public string {
public:
Number();
Number(string set);
}
The constructors are then coded as:
Number::Number() : string("0") { } // default constructor sets data string to "0"
Number::Number(string set) : string(set) { }
So far so good. Then we are to take two classes that we have been developing, Double and Integer, and derive them from Number. Within these two classes we used to have a double and an int respectively as the data member. Now, because of inheritance, we are supposed to have a built in data section (string). The issue that I am having is that all of my operator=() overloads are now "recursive on all paths" leading to a stackoverflow at runtime. I will show an example of the Double constructor that takes a string, and the equals function that causes the infinite recursion.
Double::Double(string d) : Number(d)
{
// overloaded constructor that takes a string argument
if (isNaN(d)) {
*this = "0.0";
}
else {
*this = d;
}
// used for setting the value of a data member with a string
void Double::operator=(string d)
{
if (isNaN(d)) {
*this = "0.0";
}
else {
*this = d;
}
}
}
I see where the recursion is happening as *this is calling the overloaded = which calls itself since I am using *this in the = function itself. So what would the proper syntax be for setting the data member to a supplied value. Before it was just this->dataMemberName = supplied value of proper type.
It should be noted that my non-string constructors do set the value of an instanced object:
Double::Double(int d) : Number(to_string(d)){}
but the second I try to do anything with them, + - * /, the = function is called and then the error happens again.
Just add:
using std::string::operator=;
Abbreviated example:
#include <string>
class Number : public std::string {
public:
};
class Double : public Number {
public:
using std::string::operator=;
Double()
{
*this="0.0";
}
};
After discussion in comments I decided to rewrite my answer so that it is more clear what I mean.
You should just call the base class operator= and let it handle member assignment.
You have class Number defined like this:
class Number : public string {
public:
Number();
Number(string set);
};
Can this class work for us, as we want it without any modifications? Let's look.
First thing we need is operator= in base class.
operator= is neither declared, nor deleted in class Number which means that if you call Number& Number::operator=(Number const&) this function will be generated for you by compiler. So we are good here.
Second thing which is important for my solution to work is conversion from std::string to Number.
There is constructor Number::Number(std::string) in class Number. Fortunately it's not declared explicit co it can be used implicitly (with explicit constructor it would be more verbose, but also possible). Compiler will use this constructor when it needs to convert std::string into Number. One-parameter constructors are sometimes called converting constructors.
Ok, so we have second requirement fulfilled.
That's all we need from base class!
Now to work.
We begin with creation of a helper function:
std::string check_for_NaN(std::string s)
{
if(isNaN(s)) { return "0.0"; }
return s;
}
Now we can simplify Double's constructor:
Double::Double(std::string s): Number(check_for_NaN(s)) //no magic here
{}
And we can create our long awaited operator= for class Double:
Double& operator=(std::string rhs)
{
Number::operator=(check_for_NaN(rhs)); //here we have magic, explained below
//if Double has some members of its own, copy them here
return *this;
}
So, what happens when we call 'Number::operator=(check_for_NaN(rhs));'?
check_for_NaN(rhs) returns us proper string object.
Compiler looks for Number::operator=(std::string) but can't find it.
It finds that it can generatr Number::operator=(const Number&)!
Compiler checks it such an operator would help.
It would if we could convert std::string to Number.
But we can! There is Number::Number(std::string) constructor that is not explicit!
Compiler generates assignment operator.
From std::string rhs it creates a temporary object of class Number.
Calls generated operator.
We are all happy because it worked!
You can specify directly that you want to use std::string's operator=:
#include <string>
using namespace std;
class Number : public string
{
public:
Number();
Number(string set);
};
Number::Number() : string("0") {}//default constructor sets data string to "0"
Number::Number(string set) : string(set) {}
class Double : public Number {
public:
//using Number::operator=;
Double(string d);
void operator=(string d);
double val;
};
bool isNaN(string d) { return false; }
Double::Double(string d) : Number(d) {//overloaded constructor that takes a string argument
if(isNaN(d))
{
string::operator=("0.0");
}
else
{
string::operator=(d);
}
}
void Double::operator=(string d)//used for setting the value of a data member with a string
{
if(isNaN(d))
{
string::operator=("0.0");
}
else
{
string::operator=(d);
}
}
int main()
{
Double d("3");
d = "4";
return 0;
}

Enforce function calls at compile time in C++

Is there a way in C++ to enforce function calls in compile time in such a way that this call will be allowed:
obj.reset().setParam1(10).setParam2(20);
but this one will fail to compile:
obj.reset().setParam1(10);
I want to avoid setting all parameters in one function since there are too many to be set; so I prefer to use something similar to named parameters idiom.
EDIT: Alternative syntax could be:
obj.reset(setParam1(10), setParam2(20));
or
obj.reset(setParam1(10).setParam2(20));
As the desired behaviour must be present at compile time, it needs to be implemented within the type system. To my understanding, this is impossible in C++ - the named parameters idiom relies on setter functions having the same return type (namely the type of the object which is called on), so calls to certain methods cannot be prevented.
I'll give you an example of doing that with the 2 parameters you provide, if you need more, it needs more work. If the requirement hierarchy between parameters get too complex, you may find it hard to structure your classes but here it goes:
class Obj {
Obj2 setParam2(int v);
}
class Obj2: public Obj {
Obj2 setParam1(int v);
}
int main() {
Obj obj;
obj.setParam2(10); // possible
obj.setParam2(10).setParam1(20); // possible
obj.setParam1(20); // not possible
obj.setParam1(20).setParam2(10); // unfortunately not possible
// Edit: one more limitation- consecutive calls are not possible,
// you must chain
obj.setParam2(20);
obj.setParam1(10); // problem
}
The best thing I could do to provide both named parameters and enforce all of them being initialized is this.
template<typename T>
struct Setter
{
Setter(const T &param) : ref(param) {}
const T &ref;
};
typedef Setter<int> Param1;
typedef Setter<std::string> Param2;
struct CObj
{
void reset(const Param1 &A, const Param2 &B) {
setParam1(A.ref); setParam2(B.ref); }
void setParam1(int i) { param1 = i; }
void setParam2(const std::string &i) { param2 = i; }
int param1;
std::string param2;
};
int main()
{
CObj o;
o.reset(Param1(10), Param2("hehe"));
}

C++ strategy for storing global std::string label with getter and setter

In a C++ project I'm working on, I need to keep track of a label. The label simply stores a std::string that is appended to results written to various files so that the results can be mapped to a particular phase of the implemented algorithms.
Here are the requirements of the mechanism for keeping track of the label:
All translation units need access to this label
Label must be able to be modified during runtime
Need to control access to the label via getter/setter functions
Always need exactly 1 label
This is not hard to implement. But, nonetheless, I'm raising the question here because I suspect this is something commonly done --- or, at least, very similar to things commonly done.
The best solution I can think of is to have a class such as the following, and then just include the interface everywhere:
class Label {
public:
static std::string get();
static int set(std::string s);
private:
static std::string label;
};
std::string Label::get() { return label; }
int Label::set(std::string s) {
if( /* OK to change to "s" */ ) {
label = s;
return 0;
}
return 1;
}
std::string Label::label = "";
Because there's always exactly 1 of these labels, it seems like there ought to be a better solution than creating a class. Any suggestions?
I'd tend to wonder whether there might not be more use for a broader class, something like:
template <class T>
class cond_write {
T val;
std::function<bool()> c;
public:
template <class Cond>
cond_write(T const &t, Cond c): val(t), c(c) {}
cond_write &operator=(T const &t) {
if (c())
val=t;
return *this;
}
operator T() const { return val; }
};
Then you'd instantiate it with (in your case) std::string, and a lambda for the condition under which a write can happen.
Instead of get and set, you'd just assign to it, or use it as a T (std::string, in your case). For example:
cond_write<std::string> label("Initial label", []() { return whatever(); });
// equivalent to label.set("This might be the new label");
label="This might be the new label";
// equivalent to std::string new_label = label.get();
std::string new_label=label;
I see no need for a class here and recommend using free functions and a namespace. You have the same scoping semantics but without all of the decorations such as static. They also allow you to keep internals private just as you would with a class. A few minor changes and your code ends up like the following.
Header
namespace Label
{
std::string get();
// only require a copy when necessary and allow rvalues.
int set(const std::string& s);
};
Implementation
namespace // unnamed namespace is generally recommended over using static
{
std::string label;
}
std::string Label::get() { return label; }
int Label::set(const std::string& s)
{
if( /* OK to change to "s" */ )
{
label = s;
return 0;
}
return 1;
}

C++: automatic initialization

I find it sometimes annoying that I have to initialise all POD-types manually. E.g.
struct A {
int x;
/* other stuff ... */
A() : x(0) /*...*/ {}
A(/*..*/) : x(0) /*...*/ {}
};
I don't like this for several reasons:
I have to redo this in every constructor.
The initial value is at a different place than the variable declaration.
Sometimes the only reason I have to implement a constructor is because of this.
To overcome this, I try to use my own types instead. I.e. instead of using int x,y;, I use my own vector struct which also initialize automatically with 0. I also thought about just implementing some simple wrapper types, like:
template<typename T>
struct Num {
T num;
Num() : num(0) {}
operator T&() { return num; }
operator const T&() const { return num; }
T& operator=(T _n) { num = _n; return num; }
/* and all the other operators ... */
};
This basically solves this so far for all cases where I want to init with 0 (that are by far the most often cases for me).
Thanks to James McNellis for the hint: This can also be solved via the boost::value_initialized.
Now, not limited to POD-types:
But sometimes I want to initialise with something different and there are the troubles again because that Num template struct cannot easily be extended to allow that. Basically because I cannot pass floating point numbers (e.g. float) as a template parameter.
In Java, I would just do:
class A {
int x = 42;
/*...*/
public A() {}
public A(/*...*/) { /*...*/ }
public A(/*...*/) { /*...*/ }
/*...*/
}
I find it quite important that in such cases where you want to init a member variable always in the same way in all possible constructors, that you are able to write the init value directly next to the member variable, like in int x = 42;.
So the thing I was trying to solve is to do the same thing in C++.
To overcome the problem that I cannot pass the init-value via a template parameter, I hacked together an ugly macro:
#define _LINENAME_CAT( name, line ) name##line
#define _LINENAME( name, line ) _LINENAME_CAT( name, line )
/* HACK: use _LINENAME, workaround for a buggy MSVC compiler (http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=360628)*/
#define PIVar(T, def) \
struct _LINENAME(__predef, __LINE__) { \
typedef T type; \
template<typename _T> \
struct Data { \
_T var; \
Data() : var(def) {} \
}; \
Data<T> data; \
T& operator=(const T& d) { return data.var = d; } \
operator const T&() const { return data.var; } \
operator T&() { return data.var; } \
}
(For other compilers, I can just omit that _LINENAME name for the struct and just leave it unnamed. But MSVC doesn't like that.)
This now works more or less like I want it. Now it would look like:
struct A {
PIVar(int,42) x;
/*...*/
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
/*...*/
};
While it does what I want (mostly), I still am not fully happy with it:
I don't like the name PIVar (which stands for PreInitVar) but I really couldn't come up with something better. At the same time, I want to have it short.
I don't like that macro hack.
How have you solved this? Any better solution?
There was an answer which was deleted again which said that C++0x allows basically the same syntax as in Java. Is that true? So then I would just have to wait for C++0x.
Please don't give any comments like:
"then just use Java instead" / "don't use C++ then" or
"if you need something like this, you are probably doing something wrong" or
"just don't do it this way".
Also, please don't tell me not to use it. I know about all the drawbacks of my current solution. Please only make comments about non-obvious drawbacks if you are really sure that I am not aware of that. Please don't just state that there are many drawbacks in my current solution. Please also don't state that it is not worse to use it. I am just asking if you know about a better solution than the one I have presented here.
Sometimes the only reason I have to implement a constructor is because of this.
You don't have to do that.
struct POD {
int i;
char ch;
};
POD uninitialized;
POD initialized = POD();
Equally in an initialization list:
class myclass
POD pod_;
// ....
myclass()
: pod_() // pod_'s members will be initialized
{
}
To overcome this, I try to use my own types instead.
Your type fails in this scenario:
void f(int&);
Num<int> i;
f(i);
There's likely more problems, but this is what occurred to me immediately.
How have you solved this? Any better solution?
Yes, we all have solved this. We did by not attempting to fight the language, but to use it the way it was created: initialize PODs in initialization lists. When I see this:
struct ML_LieroX : MapLoad {
std::string id;
PIVar(int, 0) type;
std::string themeName;
PIVar(int, 0) numObj;
PIVar(bool,false) isCTF;
I cringe. What is this doing? Why is it this way? Is this even C++?
All this just to save a few keystrokes typing an initialization list? Are you even serious?
Here's an old bon mot: A piece of code gets written once, but over its lifetime will be read tens, hundreds, or even thousands of times. That means that, in the long run, the time it takes to write a piece code is more or less neglectable. Even if it takes you ten times as long to write the proper constructors, but it saves me 10% of the time necessary to understand your code, then writing the constructors is what you should do.
Boost provides a value_initialized<T> template that can be used to ensure an object (POD or not) is value-initialized. Its documentation goes into great detail explaining the pros and cons of using it.
Your complaint about not being able to automatically initialize an object to a given value doesn't make much sense; that has nothing to do with the object being POD; if you want to initialize a non-POD type with a non-default value, you have to specify the value when you initialize it.
You could initialize POD structures as follows:
struct POD
{
int x;
float y;
};
int main()
{
POD a = {}; // initialized with zeroes
POD b = { 1, 5.0f }; // x = 1, y = 5.0f
return 0;
}
There is a proposal for C++0x which allows this:
struct A {
int x = 42;
};
That is exactly what I want.
If this proposal is not making it into the final version, the possibility of delegating constructors is another way of at least avoiding to recode the initialization in every single constructor (and at the same time avoiding a dummy helper function to do this).
In current C++, there does not seem to be any better way to do it despite what I have already demonstrated.
C++ does have constructor delegation, so why not use it?
struct AState
{
int x;
AState() : x(42) {}
};
class A : AState
{
A() {}
A(/*...*/) { /*...*/ }
A(/*...*/) { /*...*/ }
};
Now initialization of x is delegated by all constructors. The base constructor can even accept arguments passed from each version of A::A.
Prior to C++0x there is a solution which works well if the non-zero value you want to initialize with is not completely arbitrary (which is usually the case in practice). Similar to boost::initialized_value but with an extra argument to take the initial value (which gets a little fussy because C++).
template<typename T> struct Default { T operator()() { return T(); } };
template<typename T, T (*F)()> struct Call { T operator()() { return F(); } };
template<int N> struct Integer { int operator()() { return N; } };
template< typename X, typename Value = Default<X> >
class initialized {
public:
initialized() : x(Value()()) {}
initialized(const X& x_) : x(x_) {}
const X& get() const { return x; }
operator const X&() const { return x; }
operator X&() { return x; }
private:
X x;
};
You might use it like this:
struct Pi { double operator()() { return 3.14; } }; //Exactly
const char* init_message() { return "initial message"; }
Point top_middle() { return Point(screen_width()/2, 0); }
struct X {
initialized<int> a;
initialized<int, Integer<42> > b;
initialized<double> c;
initialized<double, Pi> d;
initialized<std::string> e;
initialized<std::string, Call<const char*, init_message> > f;
initialized<Point> g;
initialized<Point, Call<Point,top_middle> > h;
X() {}
};
I find the annoyance of having to create a dummy function to return any non-integral / non-default value is generally amortized across the entire library (since the non-zero initial values for a particular type are generally shared by many classes).
Obviously typedef is a friend here.
Anyway, can't wait to upgrade to C++0x/11/14/whatever.