Enforce function calls at compile time in C++ - 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"));
}

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

C++: Reference/pointer to member variable as template parameter

To start, I have something like this:
class Test {
std::vector<int> a, b;
void caller(...) { callee(...); }
void callee(...) { /* Do stuff with 'a' */ }
}
What I wanted is to have a function that does exactly the same as callee but for vector b. To do this there are two obvious solutions:
Pass vector a or b as argument. However, callee is a recursive function that can go for hundreds of calls, and passing the vectors as arguments would just be unnecessary overhead.
Copy the function callee and use vector b, which would be the best alternative, despite the fact that callee is quite a long function and I would have a lot of duplicate code.
Out of curiosity, I went looking for the templates part and I noticed that can be used for
lvalue reference type
pointer type
pointer to member type
So I tried to do this:
class Test {
std::vector<int> a, b;
void caller(...) { callee<a>(...); }
template <std::vector<int> &x> void callee(...) { /* Do stuff with 'x' */ }
}
but I get
error: use of ‘this’ in a constant expression
Is there any way to achieve this either with a reference or a pointer?
By the way, what I want can be seen as a function-scoped #define
Arrays and even tuples, but no love for good old pointers-to-members ?
class Test {
std::vector<int> a, b;
void caller(/*...*/) { callee<&Test::a>(/*...*/); }
template <std::vector<int> Test::*vec>
void callee(/*...*/) { /* Do stuff with `(this->*vec)` */ }
};
You cannot use a reference to a data member as a template argument: templates are compile-time, and the value of this is not known until runtime. In other words, you'd need a separate instantiation (separate binary code) for each runtime object of type Test.
What you can do is replace a and b with an array, and templatise callee by index into this array:
class Test {
std::array<std::vector<int>, 2> ab;
void caller(...) { callee<0>(...); }
template <size_t idx>
void callee(...) { /* Do stuff with 'ab[idx]' */ }
}
This way, you get only two instantiations of callee (one for 0 and one for 1), with the indexing done (or at least doable) at compile time.
Simply use a facade:
class Test {
std::vector<int> a, b;
void caller_a(...) { callee(a); }
void caller_b(...) { callee(b); }
void callee(std::vector<int> &a_or_b, ...) {
}
}
callee() will refer to its parameter, which will be passed in as one or the other class member.
In the same logic as #Angew's answer, you could also use std::tuple, and it's quite interesting as with tuple you can also use different kind of containers in your callee function :
class Test {
std::tuple<std::vector<int>, std::list<int> > ab;
void caller(...) { callee<0>(...); }
template <size_t idx>
void callee(...) {
...
auto aIt = std::get<idx>(ab).begin(); // gets either the vector or the list depending on template value
...
}
}

Method taking two default parameters

I have a method with the following definition:
void foo(int i = 0, bool flag = false) {}
I want to call foo() by passing only the second argument:
foo(true);
But like this it will always pass it to the first parameter (i).
Is there any other solution I can pass my argument to the second parameter ? Or the only way is to pass the first one also.
foo(0, true);
Technically no. But you can fake it with overloads, thusly:
void foo(bool flag)
{
foo(0,flag);
}
no. unlike python, you cannot explicitly state which parameter you want to have the value. you will have to call the method with all the parameters if you need the last one to be not the default.
It's not possible in C++, since it doesn't support named parameters: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.20
However you may use overloading:
void foo(int i, bool flag) {
//do stuff
}
inline void foo(int i) { foo(i, false); }
inline void foo(bool flag) { foo(0, flag); }
int main(void) {
foo(42);
foo(true);
return 0;
}
The former would include the base implementation and gets called by the latter ones.
Notice how they're inline.
No, when you want to pass only one parameter, you will pass the first. How the compiler could guess which parameter do you intend to use?
There's a nice "trick" called the named parameter idiom : http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.20
Here's a rough way you'd implement it for your code.
(Though its really only useful for cases where there's a lot more default/optional arguments)
class Foo
{
public:
//set the defaults
Foo():i_(100),flag_(false) {}
//provide the mutators
Foo& i(int in_i) { i_ = in_i; return *this; }
Foo& flag(int in_flag) { flag_ = in_flag; return *this; }
void operator() { foo( arg.i_, arg.flag_ ); } //Just forward to the full argument version
protected:
int i_;
bool flag_;
};
Now you can use it like this:
Foo()(); // First () creates temporary, second calls its operator()
Foo().i(20)();
Foo().flag(false)();
Foo().i(10).flag(false)();
There's some variants on this trick that you can use. You can put the arguments into a struct with mutators, but write a void foo(FooArgs) function. In this case you end up with something like:
foo( FooArgs().i(10) );
You can also call foo from from the Foo destructor rather than operator(). In that case your calls look like this:
Foo().i(20); // foo called when this temporary destructs

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.

avoiding the tedium of optional parameters

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