0

I have the following class:

class conditionStack : public Stack
{   
public:
    bool even(int);
    bool odd(int);
    bool positive(int);

    void push(bool(*)(int), int);
};

push function:

void conditionStack::push(bool (*p)(int), int a)
{
    if (p(a))
        Stack::push(a); 
}

I call function in main.cpp in the following way

conditionStack Even;
Even.push(Even.even, value);

But as a result a have the following error

error C3867: 'conditionStack::even': function call missing argument list; use '&conditionStack::even' to create a pointer to member 

I tried to call it as Even.push(&conditionStack::even, value); But it doesn't work :( Could you help me?

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
Irina
  • 37
  • 8
  • I cannot answer at the moment, but you should really use names starting with a capital letter for classes and all lower-case letters for instances. You seem to go the other way round :). – SukkoPera Nov 04 '14 at 17:47
  • 1
    @SukkoPera According to whom?? – Neil Kirk Nov 04 '14 at 17:48
  • Could you explain what problem you are trying to solve? Function pointers may not be the best solution here. Also, what does even do? – Neil Kirk Nov 04 '14 at 17:49
  • 1
    You can't create a regular function pointer to an instance method because the pointer would also have to convey in some way the object to invoke the method on. You will either have to use a pointer-to-member, or use `std::function` as your data type and use a lambda as the function: `[Even] (int i) { return Even.even(i); }` – cdhowie Nov 04 '14 at 17:53
  • The problem is the following: I have basic class Stack and I should create inheritor class which creates stack depending on selected condition. Function pointer is required in push function that's why I can't select another decision :( – Irina Nov 04 '14 at 17:55
  • @Irina Note that your function pointer type is compatible with `std::function` so if you can change the signature of `push()` then you will be able to use both function pointers and lambdas. (Assuming you have C++11 support, anyway.) – cdhowie Nov 04 '14 at 17:56
  • You should separate data structures and logic. I would not create functions such as "even" inside a stack class. Why not just `if (even(a)) mystack.push(a);` – Neil Kirk Nov 04 '14 at 17:56
  • 1
    I suspect your condition functions could be made static and used with regular function pointer but I can't tell without the definition. – Neil Kirk Nov 04 '14 at 17:57
  • If you *really* wanted to do this, your syntax is far from correct. Non-static member functions require specific operator syntax to invoke on a specific object ([see it live](http://ideone.com/wGyoZe)). I suspect as Neil does, however; this doesn't seem like the right approach from the get-go. – WhozCraig Nov 04 '14 at 18:02

2 Answers2

0

A C++ member function takes an invisible extra argument (this) which makes taking a pointer to it as above a bit more tricky.

The slightly old school way to handle them is "mem_fun"

The boost way to make it more friendly is "boost::bind"

The slightly modern way to handle them is to "C++ lambda"

Suffice to say, however, that a member function is probably of the type:

bool (*) (conditionStack *, int)

and I bet you could make that work if you really really wanted to, but as comments have suggested, please don't. It's not standard, not guaranteed, and not readable!

Alternatively, you could try making them all static member functions (static functions don't take a this argument).

A comment said I lack examples. This is true. An example could have got quite large and complex and the question isn't well enough defined to justify it (yet). There is an example of storing a vector of lambdas here : Why can't I create a vector of lambda in C++11?

Community
  • 1
  • 1
Andy Newman
  • 1,178
  • 2
  • 8
  • 23
  • 3
    Don't encourage use of undefined behaviour – Neil Kirk Nov 04 '14 at 17:54
  • Your answer suffers from lack of examples. –  Nov 04 '14 at 17:56
  • At least if I explain what the undefined behaviour is the OP can understand what problem he is trying to solve, and so will become less frustrated when google presents him with a line of gobbledegook for storing lambdas in an array :p – Andy Newman Nov 04 '14 at 17:56
  • 2
    I don't see any warning not to use your suggestion. – Neil Kirk Nov 04 '14 at 17:58
  • Why are you bringing a vector of lambdas into this? Just making it more complicated. – Neil Kirk Nov 04 '14 at 18:00
  • Because in his question he is pushing a pointer to a member function onto some sort of stack, and depending on what he is trying to achieve by that, a vector of lambdas is one way to go... – Andy Newman Nov 04 '14 at 18:02
  • She (I assume from the picture) isn't pushing the function pointer on the stack. Personally I think wrong advice with a warning not to use it is worse than just not mentioning it at all. – Neil Kirk Nov 04 '14 at 18:06
0

Function pointers that also contain information about the object instance are called delegates and were long time no standard feature in C++.

Since C++ 11 there is std::function.

You should have a look at it:

http://en.cppreference.com/w/cpp/utility/functional/function

One of the examples shows what you want:

// store a call to a member function
std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
const Foo foo(314159);
f_add_display(foo, 1);
UniversE
  • 2,419
  • 17
  • 24