I am trying to implement a member function in a C++ class which has an auto argument (a lambda) and an int argument with a default value. Something like this:
class Base {
public:
int add_one(auto fobj, int b=3);
};
int Base::add_one(auto add_fcn, int b) {
return add_fcn(1, b);
}
However, a simple test like this fails to compile:
#include <iostream>
class Base {
public:
int add_one(auto fobj, int b=3);
};
int Base::add_one(auto add_fcn, int b) {
return add_fcn(1, b);
}
int main() {
int ans;
auto add_fcn = [](int a, int b) -> int {return a + b;};
Base obj;
ans = obj.add_one(add_fcn);
std::cout << ans << "\n";
return 0;
}
The error the compiler (MinGW 7.2.0, flags: -std=c++14) gives me is the following:
error: call to 'int Base::add_one(auto:2, int) [with auto:1 = main()::<lambda(int, int)>]' uses the default argument for parameter 2, which is not yet defined
I sincerely do not understand the error. Can someone please explain me the reason of this error and how it can be fixed? Thank you in advance.
auto parameters is a gcc extension. It means that it is not a standard compliant way to solve the problem.
I am not sure what is the exact reason for the error above, but you might achieve the same effect with template member function which works well:
class Base {
public:
template<typename F>
int add_one(F fobj, int b = 3);
};
template<typename F>
int Base::add_one(F add_fcn, int b) {
return add_fcn(1, b);
}
Wandbox example
Another possible way is to use std::function (which implies some performance overhead though):
class Base {
public:
int add_one(std::function<int(int, int)> fobj, int b = 3);
};
int Base::add_one(std::function<int(int, int)> add_fcn, int b) {
return add_fcn(1, b);
}
Wandbox example
Finally, you could make use of pointers to functions, but it is too C way...
If you'd like to expand your knowledge on passing functions to functions, this article by Vittorio Romeo gives an excellent explanation + some benchmarks.
Related
I'd want to use a function pointer in my template argument list. I do miss something of B even I am writing int in full main of both A and B. I have a class X.h like so, don't know which one it is now causing the error.
struct X
{
int fun(int a)
{
return a;
}
template<typename A, typename B>
A func(int x, B(*f)(int))
{
A i = 10;
return i + f(x);
}
};
and I like to use it in main.cpp
int main()
{
X d;
std::cout << d.func<int, int>(10, &X::fun) << "\n";
return 0;
}
The error is No instance of func matches the argument list...
The problem is that the argument &X::fun is of type int (X::*)(int) while the parameter f is of type int(*)(int) (when B = int) and there is no implicit conversion from the former to the latter and hence the error.
To solve this you can change the parameter f to be of type B(X::*)(int) as shown below. Note that the syntax for making a call using member function pointer is different for making a call to a free function.
With C++17, we can use std::invoke.
struct X
{
int fun(int a)
{
return a;
}
template<typename A, typename B>
//------------------vvvv-------------->added this X:: here
A func(int x, B(X::*f)(int))
{
A i = 10;
//-----------------vvvvvvvvvv-------->this is the syntax to call using member function pointer
return i + (this->*f)(x);
//return std::invoke(f, this, x); //use std::invoke with C++17
}
};
int main()
{
X d;
std::cout << d.func<int, int>(10, &X::fun) << "\n"; //works now
return 0;
}
Working demo
I am using function overload to have a general version of a behaviour and a more usual one. The usual function just picks a default value for the second argument that actually depends on the first, and the compiler is giving me an error because it does not even recognize the existence of the second function. I also tried to do it with default values, but because the default depends on the first argument, the compiler does not seem to accept it.
So, here are simplified examples just for illustration.
Function overloading case:
#include <stdio.h>
struct pair {
int x;
int y;
};
int func(pair a){
return func(a, a.y);
}
int func(pair a, int b) {
return a.x*b;
}
int main() {
pair z;
z.x = 2;
z.y = 4;
printf("%d\n", func(z));
printf("%d\n", func(z,12));
}
This gives me the error:
a.c: In function ‘int func(pair)’:
a.c:9:21: error: too many arguments to function ‘int func(pair)’
a.c:8:5: note: declared here"
Example with default values:
#include <stdio.h>
struct pair {
int x;
int y;
};
int func(pair a, int b = a.y) {
return a.x*b;
}
int main() {
pair z;
z.x = 2;
z.y = 4;
printf("%d\n", func(z));
printf("%d\n", func(z,12));
}
Gives me the following error: "local variable a may not appear in this context"
So, is there any way in C++ to emulate this behaviour? I never had this problem in other languages, like Java or even in ASP.
Thank you all.
In C and C++, before the function call, that function should be declared or defined. Here you are making a call to return func(a, a.y); but the function func(pair, int) has not yet been declared or defined.
You need to change the definitions of the two functions, or just declare the functions in the beginning of your code. As other answers have explained the first approach, here is the snippet with second approach.
#include <stdio.h>
//Function Declaration
int func(pair);
int func(pair, int);
struct pair {
int x;
int y;
};
int func(pair a){
return func(a, a.y);
}
int func(pair a, int b) {
return a.x*b;
}
int main() {
pair z;
z.x = 2;
z.y = 4;
printf("%d\n", func(z));
printf("%d\n", func(z,12));
}
Switch the order of the definitions of func(), such that the 2 argument version is defined before the one argument version. The compiler doesn't know the 2 argument version exists until it encounters the definition, so you can't call it until you've told the compiler it exists.
You have to change the order of the definitions:
int func(pair a, int b) {
return a.x*b;
}
int func(pair a){
return func(a, a.y);
}
LIVE DEMO
This is happening because in int func(pair a) you are calling int func(pair a, int b) which is not visible. Changing the order of definitions like above solves this problem.
I wish to create many functions with the same parameters, for example:
const int add(const int a, const int b) {
return (a + b);
}
decltype(add) subtract {
return (a - b);
}
/* many more functions */
The purpose being that I am able to easily change the types of the parameters once to change all of the functions. I know that this is possible with macros as so:
#define INT_OPERATION(name) const int name (const int a, const int b)
INT_OPERATION(add) { return (a + b); }
INT_OPERATION(subtract) {return (a - b); }
However, I dislike the use of macros. Is there a safer way of doing this?
A function signature cannot be typedefed. Only a function's type. So it's valid to say :
typedef int INT_OPERATION(int a, int b);
and then forward declare a function having this type :
INT_OPERATION Add;
but when it comes to defining the function you'd have to specify arguments, so the follwing is invalid
INT_OPERATION Add { /* No can do */ }
(as soon as you place a set of () after Add you'll be declaring a function returning a plain function which is not valid C++)
On generic types
The same procedure has similar limitations when using the tools for generic programming. You can declare the following typedef :
template<typename T>
using INT_OPERATION = const T(T const, T const);
And then use it for a function (forward) declaration
INT_OPERATION<int> add;
int main() {
std::cout << add(1, 2) << std::endl;
return 0;
}
but when it comes to defining it, you'd have to be mandane
const int add(int const a, int const b) {
return a + b;
}
Demo
Maybe something like that:
#include <iostream>
#include <functional>
typedef std::function<int(int, int)> IntFunction;
IntFunction add = [](int a, int b) {return a + b;};
IntFunction substract = [](int a, int b) {return a - b;};
int main(int, char**) {
std::cout << add(1, 2) << std::endl;
std::cout << substract(1, 2) << std::endl;
return 0;
}
Still boilerplate code, but worth a try ;)
If these were member functions you could declare their common type (typedef const int Fn(int, int)), declare the member functions inside the class using that type:
Fn add, subtract;
Then you define them outside the class in the normal way. Doesn't save boilerplate, but at least means it won't compile if you make a typo in the definitions.
Alternatively for non member functions see the question I linked to which has some clever ways to define function pointers rather than functions.
If your primary concern is being able to "easily change the types of the parameters", it's straightforward to write them as templates so that you never have to change the types of the parameters:
template <typename T1, typename T2>
auto add (const T1 &a, const T2 &b) -> decltype(a + b) {
return (a + b);
}
This also handles cases where a and b are not of the same type, or where a + b is not the same type as a or b.
This question already has answers here:
How do you pass a member function pointer?
(6 answers)
Closed 9 years ago.
I have a class
class A{
A(/*constructor arguments*/);
double MethA(double);
};
And I want to pass the method MethA in a function that takes a pointer to a function :
double function(double (*f)(double), double x){
return f(x);
}
So what I'm doing is to call
A a(/*constructor arguments*/);
function(a.MethA,1.0);
but it doesn't compile.
I'm pretty sure that this question is answered somewhere else, but I couldn't find where because I'm not sure that the terminology I use is correct. Am I trying to pass a pointer on a class method as a function argument ? Or, to pass a function pointer as a member of a class... I'm confused :-(
When you need to use a pointer to member function, you need to pass two separate things:
what member function to call and
what instance to call it on.
In C++, you can't combine them in one construct, like you want to:
A a;
bar(a.foo);
is not valid C++.
Instead, you have to do this:
A a;
bar(a, &A::foo)
And declare and implement bar() accordingly:
void bar(A &a, void (A::*method)()) {
a.*method();
}
See Arkadiy's answer if you want to see how to properly use member function pointers.
BUT
As requested in the comments: if the compiler you are using supports lambdas (some without full C++11 do). You can do something like the following, which looks more like the syntax you are attempting to use.
Your definition for function changes to something like:
template <typename F>
double function(F f, double x){
return f(x);
};
a function template that accepts a parameter that is callable with a double.
At your call-site you do this:
A a(/*constructor arguments*/);
function([&](double x){return a.MethA(x);},1.0);
That generates a function object in-place that is bound to your class instance a by reference.
The template can be made fully typesafe with some magic in <type_traits>, but as-is it will give you template spew if you pass something very wrong.
It has to be a static function!
#include <iostream>
#include <cassert>
class A {
public:
static double MethA(double x) { return 5 * x; }
};
typedef double (*ftype)(double);
double function(ftype f) {
assert(f != NULL);
return f(7);
}
int main(int, char**) {
// expect "35\n" on stdout
std::cout << function(A::MethA) << "\n";
}
It has to be static because you can't access any of A's variables without knowing which A object are you refering to! If you need A's non-static member variables, you need to pass a reference to an a into the static function:
#include <iostream>
#include <cassert>
class A {
double fX;
public:
A(double x) : fX(x) { }
double methB(double x) const { return fX * x; }
static double MethB(double x, const A& a) {
return a.methB(x);
}
};
typedef double (*ftype2)(double, const A&);
double function_with_context(ftype2 f, const A& a) {
assert(f != NULL);
return f(7, a);
}
int main(int, char**) {
A a(6);
// expect "42\n" on stdout
std::cout << function_with_context(A::MethB, a) << "\n";
}
But it's sometimes better to use inheritance and polymorphism to achieve this sort of interface:
#include <iostream>
class MyInterface {
public:
virtual double f(double x) const = 0;
};
class A : public MyInterface {
double fX;
public:
A(double x) : fX(x) { }
double f(double x) const {
return fX * x;
}
};
double function(const MyInterface& o) {
return o.f(7);
}
int main(int, char**) {
A a(6);
// expect "42\n" on stdout
std::cout << function(a) << "\n";
}
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;
}