0

The code below does not compile. The function foo takes a function pointer f as an argument, and f strictly takes one int as argument and returns an int. In this example, foo always invokes f with the argument 3. I would like to pass a function to foo so that when f(3) is evaluated, it's evaluated in conjunction with some other parameter; however, I can't pass a function with 2 ints as arguments to foo (this problem is an analogy for a real problem).

#include <iostream>

void foo(int(*f)(int))
{
  std::cout << f(3) << std::endl;
}

struct plusX
{
  plusX(int x_) : x(x_) {}
  int x;
  int plus(int y)
  {
    return x + y;
  }
};

int main()
{
  plusX px4(4);
  foo(&px4.plus);  // ERROR!
}

ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&plusX::plus'

Agrim Pathak
  • 3,047
  • 4
  • 27
  • 43
  • C and C++ are totally different my dear friend. use one of the tag – Dilip Kumar Oct 28 '15 at 02:01
  • Look up "pointer to member function". It's not the same as a regular function pointer. Ground well covered in the past; cba to find the dupe(s). – Lightness Races in Orbit Oct 28 '15 at 02:03
  • what is 'a' in your code? Is that supposed to be 'foo'? – codesniffer Oct 28 '15 at 02:06
  • 2
    @AgrimPathak it's not about the std::cout, it's the fact that member functions inside structs don't exist in C, which is the fundamental issue you're asking about. – etheranger Oct 28 '15 at 02:31
  • "despite the std::out"? What about the fundamental problem that a pointer to a member function is different than a plain old function pointer - that's what really makes this not a C question. – Michael Burr Oct 28 '15 at 02:31
  • `int(*f)(int)` can only point to a non-member function. Possible solutions are (a) point it to a non-member function, (b) use a pointer-to-member and a pointer-to-object, (c) use `std::function`. The latter is easiest – M.M Oct 28 '15 at 02:36
  • @codesniffer Yes sorry, a is foo (edited now). Wanted to give it a better name. – Agrim Pathak Oct 28 '15 at 02:49
  • take a look at [this question](http://stackoverflow.com/q/30609314/2174266) – vagoberto Oct 28 '15 at 02:53
  • @Porges I don't agree that my question is a dupe to the question you posted. Did you understand the question? I'm still trying to figure this out, and it would've been nice seeing full answers with code. I believe the solution is more along the lines of std::function and std::bind, but still trying to arrive at a solution. – Agrim Pathak Oct 28 '15 at 03:29
  • I disagree that this is a duplicate of the proposed question [C++, function pointer to member function] (http://stackoverflow.com/questions/2402579/c-function-pointer-to-member-function). That question is specifically looking for a **member** function pointer to reference another **member** function. So the answer there is different because there's no need to explicitly handle the "this" ptr along w/ the function pointer. This question is about calling a member function from a non-member function. – codesniffer Oct 30 '15 at 06:31
  • (I'd have submitted this as a possible answer if this question weren't already closed as a duplicate). There are other ways to solve this depending on what your requirements are on modifying the code (ie. are you allowed to change foo or plusX?). A couple other ways to enable this is to make foo a template function and then either have it call the 'plus' method on the object passed to it, or--if C++11 is allowed--via a lambda at the call site. – codesniffer Oct 30 '15 at 06:36
  • @codesniffer Thanks for understanding this isn't a dupe!! Unfortunately, so many questions hastily get marked as a dupe without voters having a clue of what's being asked (//end rant). I'd love to read your answer. Yes, plusX and foo can be modified and this is C++11. Is there anyway this can be reopened? – Agrim Pathak Oct 30 '15 at 15:45
  • I don't know what's involved in getting this question re-opened to accept answers. My guess is that one or more of @Porges, TheDark, godel9, Smac89, m.s. needs to change their mark. I've put my suggestions at (https://codesniffer.com/scratch/stackoverflow/parameterizing-a-function-using-a-struct/main.cpp) for you. – codesniffer Nov 02 '15 at 13:24

1 Answers1

0

Two solutions. The first solution doesn't require refactoring code if existing code uses functions.

1) Using functors:

#include <iostream>

template<typename F>
void foo(F&& f)
{
  std::cout << f(3) << std::endl;
}

struct my_functor
{
  my_functor(int x_) : x(x_) {}
  int operator()(int y)
  {
    return x + y;
  }
  int x;
};

int main()
{
  my_functor f(4);
  foo(f);
}

2) Using std::function and std::bind

#include <iostream>
#include <functional>

void foo(const std::function<int(int)>& f)
{
  std::cout << f(3) << std::endl;
}

int add(int x, int y)
{
  return x + y;
}

int main()
{
  std::function<int(int)> f_binded = std::bind(add, 4, std::placeholders::_1);
  foo(f_binded);
}
IKavanagh
  • 6,089
  • 11
  • 42
  • 47
Agrim Pathak
  • 3,047
  • 4
  • 27
  • 43
  • Please use the edit link on your question to add additional information. The Post Answer button should be used only for complete answers to the question. – ForceMagic Oct 28 '15 at 05:54
  • I added some more info. How is the answer incomplete? – Agrim Pathak Oct 28 '15 at 07:04
  • Well, at first it seemed unclear to me why you'd answer your own question instead of editting it. Until I realized, you kinda answering two problem from your question. IMO the question is not clear at first and the answer is not explaining why these are valid solution. Sorry – ForceMagic Oct 28 '15 at 17:12
  • I don't know what you mean by "two problems". It's 1 problem, but I provided two different ways of solving it, the first one being better. – Agrim Pathak Oct 28 '15 at 18:45