Is there a nice way to have a non static value as default argument in a function? I've seen some older responses to the same question which always end up in explicitly writing out the overload. Is this still necessary in C++17?
What I'd like to do is do something akin to
class C {
const int N; //Initialized in constructor
void foo(int x = this->N){
//do something
}
}
instead of having to write
class C {
const int N; //Initialized in constructor
void foo(){
foo(N);
}
void foo(int x){
//do something
}
}
which makes the purpose of the overload less obvious.
One relatively elegant way (in my opinion) would be to use std::optional to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
I have something like
struct Foo {
const double a;
const double b;
Foo(double c);
}
Foo::Foo(double c) {
double tmp = f(c);
a = g(tmp);
b = h(tmp);
}
where f,g,h are functions implemented elsewhere. This gives the expected "uninitialized const member" error.
I could fix it with
Foo::Foo(double c): a (g(f(c))), b (h(f(c))) {}
but f is an expensive function and I wouldn't like to run it twice.
My question is, how can I solve this problem without running f twice or making tmp a permanent member of Foo?
Typically, delegating constructors offer a simple solution to this type of problem. In this case you'll have to introduce some way to distinguish between the two constructors:
private:
// the int param is unused
Foo(double fc, int) : a(g(fc)), b(h(fc)) {}
public:
Foo(double c) : Foo(f(c), 0) {}
Why are default arguments in C++ trailing ones?
if you had void func(int a = 0, int b);, how would you specify to use the default parameter in calling this function?
Because that is how the language has been designed.
A more interesting question would be: what are the alternatives?
Suppose you have void f(A a = MyA, B b);
Placeholder / blank argument: f(_, abee) or f(, abee)
Named arguments (like in Python): f(b = abee)
But those are niceties and certainly not necessary, because unlike Python C++ supports function overloading:
void f(A a, B b);
void f(B b) { f(MyA, b); }
and thus the default arguments are unnecessary... especially considering that there are issues when used with polymorphic code because default arguments are statically resolved (compile-time).
struct Base
{
virtual void func(int g = 3);
};
struct Derived
{
virtual void func(int g = 4);
};
int main(int argc, char* argv[])
{
Derived d;
d.func(); // Derived::func invoked with g == 4
Base& b = d;
b.func(); // Derived::func invoked with g == 3 (AH !!)
}
Regarding named parameters:
The feature can be emulated using function objects.
class Func
{
public:
Func(B b): mA(MyA), mB(b) {}
A& a(A a) { mA = a; }
B& b(B b) { mB = b; }
void operator()() { func(mA, mB); }
private:
A mA;
B mB;
};
int main(int argc, char* argv[])
{
A a;
B b;
Func(b)();
Func(b).a(a)();
}
In case you don't want to copy the arguments, you have the possibility to use references/pointers though it can get complicated.
It's a handy idiom when you have a whole lot of defaults with no real order of priority.
Just to supplement #tenfour's answer. C++ FAQ Lite has a topic describing named parameters and I think the topic addresses your issue to some extent.
Because in a function call you have to call the non-default arguments in any case. If you put your default argument at the beginning of the argument list, how are you supposed to say you are setting the default argument or the other ones?
So I know it is disallowed to have functions with the same parameters and names:
int a(int b) {
return b;
}
int a(int b) {
return b;
}
int main() {
int c = a(4);
}
This above won't compile. But then I got thinking, what if I passed one by reference, and one by value?
int a(int b) {
return b;
}
int a(int& b) {
return b;
}
int main() {
int c = a(4);
}
The above does compile, I guess because you can't pass 4 to by reference, so it assumes you want the first a, which means the compiler can distinguish which function you want to call. If I then change main to this:
int main() {
int c = a(4);
a(c);
}
It will fail to compile, I assume because c can be passed to either function, so the compiler doesn't know which function to call.
But what about... THIS?
int a(const int& b) {
return b;
}
int a(int& b) {
return b;
}
int main() {
int c = a(4);
a(c);
}
This does compile. Why? I expected it to not, because c can be passed to both the first and second a. Is there some misconception I have?
My question specifically is, how come this (code below) does not compile, and the final one does?
int a(int b) {
return b;
}
int a(int& b) {
return b;
}
int main() {
int c = a(4);
a(c);
}
If I was the compiler, and I could choose which function to call based how close the parameters matched, for the call a(c), I could choose from both the first and second. Is there any reason that the first or second a cannot be chosen from in this example?
The process of choosing the correct function to use from a function call is called Overload Resolution. When a function is called, the compiler searches for all functions with that name (overloads) and compiles them into an overload set. Simply put, a best match is chosen by picking the functions that require the least conversions as possible from their parameters.
These are the two functions compiler chooses from a(c):
int a(const int& b);
int a( int& b);
The second overload is chosen because the first overload requires a const-qualification. The variable with which you called the function with, c, is non-const, so it is a perfect match for the second overload and can be bound to the non-const reference.
int a(const int& b) {
return b;
}
int a(int& b) {
return b;
}
int main() {
int c = a(4);
a(c);
}
When you call it with a(4) 4 is a literal and only your version taking a const reference can bind it, so that's the one being called.
Now when you call a(c) you got c as a non-const int it will therefore prefer the function taking a non-const reference.
I suspect this is impossible, but thought I'd ask. Say I have a class with a method:
class A {
public:
void b(int c);
};
I can make a pointer to that member function:
void (A::*ptr)(int) = &A::b;
(someAInstance.*ptr)(123);
I can also abuse function pointers and make a pointer that takes the A argument directly (I don't know if this is safe, but it works on my machine):
void (*ptr2)(A*, int) = (void (*)(A*, int))&A::b;
(*ptr2)(&someAInstance, 123);
What I want is to somehow curry the A argument, and create a function pointer that just takes an int, but calls the A::b method on a particular A instance I've predefined. The A instance will stay constant for that particular function pointer, but there may be several function pointers all pointing to the same A::b method, but using different A instances. For example, I could make a separate wrapper function:
A* someConstantA = new A;
void wrapper(int c) {
someConstantA->b(c);
}
void (*ptr3)(int) = &wrapper;
Now I can use ptr3 without knowing which particular A it's dispatching the call to, but I had to define a special function to handle it. I need a way to make pointers for any number of A instances, so I can't hardcode it like that. Is this in any way possible?
Edit: Should've mentioned, I'm trapped in C++03 land, and also can't use Boost
Don't create a wrapper function, create a wrapper functor. This allows you to encapsulate whatever state you want to (e.g. an A*) in a callable object.
class A {
public:
void b(int c) {}
};
struct wrapper {
A* pA;
void (A::*pF)(int);
void operator()(int c) { (pA->*pF)(c); }
wrapper(A* pA, void(A::*pF)(int)) : pA(pA), pF(pF) {}
};
int main () {
A a1;
A a2;
wrapper w1(&a1, &A::b);
wrapper w2(&a2, &A::b);
w1(3);
w2(7);
}
If you have a sufficiently new compiler (e.g. gcc 4.2+), it should include TR1, where you could use std::tr1::bind:
#include <cstdio>
#include <tr1/functional>
class A {
public:
void b(int c) {
printf("%p, %d\n", (void*)this, c);
}
};
int main() {
A* a = new A;
std::tr1::function<void(int)> f =
std::tr1::bind(&A::b, a, std::tr1::placeholders::_1); // <--
f(4);
delete a;
return 0;
}
It is also doable in pure C++03 without TR1, but also much more messier:
std::binder1st<std::mem_fun1_t<void, A, int> > f =
std::bind1st(std::mem_fun(&A::b), a);
You could also write your own function objects.
Note that, in all the above cases, you need to be very careful about the lifetime of a since that is a bare pointer. With std::tr1::bind, you could at least wrap the pointer in a std::tr1::shared_ptr, so that it can live just as long as the function object.
std::tr1::shared_ptr<A> a (new A);
std::tr1::function<void(int)> f =
std::tr1::bind(&A::b, a, std::tr1::placeholders::_1);
If you are using C++11, you might use a lambda (untested code):
template<typename T, typename A>
std::function<void(A)> curry(T& object, void (T::*ptr)(A))
{
return [](A a) { (object.*ptr)(std::forward<A>(a)); }
}
I'd be using Boost::bind for this.
Basically:
class A
{
int myMethod(int x)
{
return x*x;
}
};
int main(int argc, char* argv[])
{
A test();
auto callable = boost::bind(&A::myMethod, &A, _1);
// These two lines are equivalent:
cout << "object with 5 is: " << test.myMethod(5) << endl;
cout << "callable with 5 is: " << callable(5) << endl;
return 0;
}
I think that should work. I'm also using auto in here to deduce the type returned by boost::bind() at compile-time, which your compiler may or may not support. See this other question at stackoverflow for an explanation of the return type of bind.
Boost supports back to Visual Studio 2003 (I think) and this all this will work there, though you'll be using BOOST_AUTO I think. See the other question already linked for an explanation.
What you want to do is not possible.
To see why, assume that it is possible - the function pointer must point to a function somewhere in your executable or one of its libraries, so it must point to a function that knows which instance of A to call, much like your wrapper function. Because the instance of A is not known until runtime, you'd have to create those functions at runtime, which isn't possible.
What you're trying to do is possible in C++03, as long as you're happy to pass around a function object rather than a function pointer.
As others have already given solutions with C++11 lambdas, TR1 and boost (all of which are prettier than the below), but you mentioned you can't use C++11, I'll contribute one in pure C++03:
int main()
{
void (A::*ptr)(int) = &A::b;
A someAInstance;
std::binder1st<std::mem_fun1_t<void,A,int> > fnObj =
std::bind1st(std::mem_fun(ptr), &someAInstance);
fnObj(321);
};
I've worked something out with a template Delegate class.
// T is class, R is type of return value, P is type of function parameter
template <class T, class R, class P> class Delegate
{
typedef R (T::*DelegateFn)(P);
private:
DelegateFn func;
public:
Delegate(DelegateFn func)
{
this->func = func;
}
R Invoke(T * object, P v)
{
return ((object)->*(func))(v);
}
};
class A {
private:
int factor;
public:
A(int f) { factor = f; }
int B(int v) { return v * factor; }
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a1 = new A(2);
A * a2 = new A(3);
Delegate<A, int, int> mydelegate(&A::B);
// Invoke a1->B
printf("Result: %d\n", mydelegate.Invoke(a1, 555));
// Invoke a2->B
printf("Result: %d\n", mydelegate.Invoke(a2, 555));
_getch();
delete a1;
delete a2;
return 0;
}