Alternatives to using class attribute value as a method default parameter? - c++

I want to achieve something like this:
class C
{
int m_nVal;
public:
C(int nVal) : m_nVal(nVal){}
void foo(int nVal = m_nVal)
{
// use nVal, if provided; otherwise use m_nVal
}
};
C c(1);
c.foo(); // use 1
c.foo(2); // use 2
This is not possible as C++ standard says:
a non-static member shall not be used in a default argument
Options I have are:
(1) Overload foo():
class C
{
int m_nVal;
public:
C(int nVal) : m_nVal(nVal){}
void foo()
{
// use m_nVal
}
void foo(int nVal)
{
// use nVal
}
};
(2) Use static member:
class C
{
static int m_nVal;
public:
void foo(int nVal = m_nVal)
{
// use nVal, if provided; otherwise use m_nVal
}
};
I don't want to make m_nVal static member so option 1 seem the only one.
Are there any other ways to achieve this?

There are other alternatives if you are willing to change the interface. You can use boost::optional:
// untested:
void foo( boost::optional<int> val = boost::optional<int>() ) {
int value;
if ( val ) value = *val;
else value = m_val;
// Now use `value` in the function
}
If you cannot use boost, you can write your own nullable wrapper. You just need to store the type (int) and a flag that determines whether it is set or not.
The next option is using a pointer to mark that the argument is optional:
void foo( int *pval = 0 ) {
int value = (pval? *pval : m_val);
// use value from here on
}
But the option with the pointer inhibits the use of rvalues as arguments to the function (i.e. you need a proper variable to call the function, you cannot do foo(1) but rather need to do int x = 1; foo( &x );, which is kind of a pain).
Finally you can use your approach of offering two overloads, one that takes the argument and one that doesn't and just forwards to the first:
void foo( int val ) {
// actual implementation
}
void foo() {
foo( m_val );
}
This might actually be the best option...

The two options aren't equivalent. Making a member static shouldn't be a decision made on whether you want to use it as a default to a method or not.
If m_nVal is logically bound to the class, and not an instance, make it static.
If m_nVal is specific to each object of the class, don't, and use the first option.

Passing default parameter would mean compiler has to pass it. It would mean, for m_nVal, the compiler would use this->m_nVal. This would, in turn, mean `foo(this->m_nVal);'.
This is what I mean:
c.foo(c.m_nVal); // use 1
Which would allow m_nVal private data to be accessed outside class, and breaks basic C++ rule.

class C
{
int m_nVal;
public:
C(int nVal) : m_nVal(nVal){}
void foo(int nVal = -1)
{
if(nVal == -1)
nVal = m_nVal;
// use nVal, if provided; otherwise use m_nVal
}
};
C c(1);
c.foo(); // use 1
c.foo(2); // use 2

Related

Passing default parameter to function C++

I want to call function either with default arguments or given by me, but default arguments are specified class private variables, simplified sample here:
Class::Something
{
public:
void setI(int i);
private:
void func(int i = this->i_default, j=this, k=this->k_default, l=this->l_default);
int i_default; // May be different for different instances.
int k_default; // May be different for different instances.
int l_default; // May be different for different instances.
}
So when i call func() it takes default i_variable or when i call func(4) it takes 4 argument without changing i_default value.
I know im doing something wrong couse i get error:
Error 1 error C2355: 'this' : can only be referenced inside non-static member functions or non-static data member initializer
is there some kind of way to achive such behaviour?
is there some kind of way to achive such behaviour?
Use function overload (Thanks #PiotrSkotnicki):
void func(int i);
void func() { func(i_default); }
You can declare i_default as const static (Thanks to #TartanLama).
const static int i_default=1;
Here is the working program.
You can also use function overloading. But this uses less code than function overloading!
The standard is quite clear about this. You explicitely cannot use this in the default parameter. You seem to be bound to use overloading for achieving this result:
void func(int i);
void func() { func(i_default); }
If you want to keep down the functions you could use a sentry that would allow func decide if it's to use the default. In the simpliest form:
void func(int* pi = NULL) {
int i = pi ? *pi : i_default;
// rest of the function
}
This method could be extended to use a helper class:
#include <cstdio>
template <typename C, typename T>
class Defaltable {
T val;
T C::* ptr;
public:
Defaltable(int C::* p) {
ptr = p;
val = 0;
}
Defaltable(T x) {
val = x;
ptr = NULL;
}
T fetch(C* p) {
return ptr ? p->*ptr : val;
}
};
class Foo {
int i_default;
public:
Foo(int dflt) {
i_default = dflt;
}
int func(Defaltable<Foo, int> x = &Foo::i_default) {
return x.fetch(this);
}
};
int main()
{
Foo c(42);
printf("%d\n", c.func(1));
printf("%d\n", c.func());
}

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

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.

C++: inheritance problem

It's quite hard to explain what I'm trying to do, I'll try: Imagine a base class A which contains some variables, and a set of classes deriving from A which all implement some method bool test() that operates on the variables inherited from A.
class A {
protected:
int somevar;
// ...
};
class B : public A {
public:
bool test() {
return (somevar == 42);
}
};
class C : public A {
public:
bool test() {
return (somevar > 23);
}
};
// ... more classes deriving from A
Now I have an instance of class A and I have set the value of somevar.
int main(int, char* []) {
A a;
a.somevar = 42;
Now, I need some kind of container that allows me to iterate over the elements i of this container, calling i::test() in the context of a... that is:
std::vector<...> vec;
// push B and C into vec, this is pseudo-code
vec.push_back(&B);
vec.push_back(&C);
bool ret = true;
for(i = vec.begin(); i != vec.end(); ++i) {
// call B::test(), C::test(), setting *this to a
ret &= ( a .* (&(*i)::test) )();
}
return ret;
}
How can I do this? I've tried two methods:
forcing a cast from B::* to A::*, adapting a pointer to call a method of a type on an object of a different type (works, but seems to be bad);
using std::bind + the solution above, ugly hack;
changing the signature of bool test() so that it takes an argument of type const A& instead of inheriting from A, I don't really like this solution because somevar must be public.
EDIT:
Solution (1) is:
typedef bool (A::*)() mptr;
std::vector<mptr> vec;
vec.push_back(static_cast<mptr>(&T::test));
std::vector<mptr>::iterator i;
for(i = vec.begin(); i != vec.end(); ++i) {
(a .* (*i))();
}
I'm not sure the static cast is safe.
The cleanest solution is the last one you suggest, make test a (pure) virtual function in A:
virtual bool test(const A& value) = 0;
If you're bothered with making somevar public keep it private and supply only a public get function:
int getvar() const {return somevar;}
You are trying to call B and C methods on an A. Don't do that.
You need to create actual instances of B and C, store pointers to them in a vector<A*> and, during iteration, call a pure virtual test() member function defined in A (which B::test and C::test will override).
Add "virtual bool test() = 0;" in the definition of A.
Then you can do the following in your loop:
ret = (ret && i->test());
BTW: "&=" does a "bitwise and" and you probably want the logical and to be performed (&&).
Also: the instances of B and C you put pointers to in your vector all contain copies of the inherited variable, they are all independant instantiations of that variable.
I think your code, as shown here, is pretty flawed. Think more about what it is you want to actually achieve?
Do you want to run a multiplicity of boolean tests on a single variable and see if it matches all of them?
Or is each contraint really to be tested against its own variable and you want to get the "boolean and" of all those independent tests?
This is the cleanest solution so far. It uses static:
struct A {
int somevar;
};
struct B {
static bool test(const A& a) {
return (a.somevar == 42);
}
};
std::vector<bool (*)(const A&)> vec;
template<typename T>
void push(const T&) {
vec.push_back(&T::test);
}
The simple solution:
Change class A to:
class A {
public:
virtual bool test() const = 0;
protected:
int somevar;
// ...
};
Now, I need some kind of container that allows me to iterate over the elements i of this container, calling i::test() in the context of a.
typedef std::vector<A*> ItemList;
ItemList items;
for(ItemList::const_iterator i = items.begin(); i != items.end(); ++i)
{
if((*i)->test())
; // ???
}
So I'm wondering what the OP wants to do that this doesn't...