4

Reference: [33.11] Can I convert a pointer-to-function to a void*?

#include "stdafx.h"
#include <iostream>

int f(char x, int y) { return x; }
int g(char x, int y) { return y; }

typedef int(*FunctPtr)(char,int);

int callit(FunctPtr p, char x, int y)  // original
{
    return p(x, y);
}

int callitB(FunctPtr p, char x, int y) // updated
{
    return (*p)(x, y);
}

int _tmain(int argc, _TCHAR* argv[])
{
    FunctPtr p = g;                    // original
    std::cout << p('c', 'a') << std::endl;

    FunctPtr pB = &g;                  // updated
    std::cout << (*pB)('c', 'a') << std::endl;

    return 0;
}

Question> Which way, the original or updated, is the recommended method? I have tested both methods with VS2010 and each prints the correct result.

Thank you

Although I do see the following usage in the original post:

 void baz()
 {
   FredMemFn p = &Fred::f;  ← declare a member-function pointer
   ...
 }
q0987
  • 34,938
  • 69
  • 242
  • 387

4 Answers4

6

Dereferencing a function pointer yields another function pointer. So, just f(), otherwise you're only obfuscating your code.

Pointers to members are different beasts altogether. They require usage of .* or ->* operators. That's also why you should use std::function (or boost::function) instead of raw pointers to functions/memebers.

Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
  • 3
    Perhaps one should consider that `std::function` comes with considerable overhead, though, so in a crunch, a straight-up PTMF might be preferable. – Kerrek SB Nov 22 '11 at 17:50
  • @KerrekSB do you know any recent benchmarks? I came accross an article on codeproject that provides a hacky implementation of fast delegates along with bechmarks, but its data is rather old IIRC. – Tamás Szelei Nov 22 '11 at 17:59
  • 1
    @TamásSzelei: Afraid not, but I know that `std::function` is essentially forced by design to use type erasure internally which requires virtual dispatch and dynamic allocation, and I have a hunch that this cannot be optimized away for fundamental reasons. So if you're in a tight loop or need memory-locality, there might be a genuine price to pay. I'd also be very curious to see comparisons, though! – Kerrek SB Nov 22 '11 at 18:02
  • There are several "fast delegate" articles on codeproject which claim to be faster (there are ones that are standard-compliant). I think it can be optimized, if the compiler recognizes the class as an "internal" and treats it appropriately. Is there an article that explains the need for type erasure and dynamic dispatch? I'd like to learn about it. – Tamás Szelei Nov 22 '11 at 19:16
  • I disagree with the second paragraph. Member function pointers and `std::function` solve two different problems, to say "use one over the other" ignores that difference. – GManNickG Nov 22 '11 at 19:34
  • @TamásSzelei: [This](http://stackoverflow.com/questions/6122094/building-boostoptions-from-a-string-boostany-map/6123962#6123962) may be useful. – GManNickG Nov 22 '11 at 19:35
6

Both are okay:

  p();
(*p)();

But the first one is preferable, because it is more consistent with functor object. For example, you can write a function template as:

template<typename Functor>
void f(Functor fun)
{
     fun(); //uniform invocation - it doesn't matter what it is.
}

Now this can be called with function pointers, and functor object, both, which has been made possible only because I have used the first syntax.

The moral of story is : strive for uniform invocation. Write code in such a way that invocation syntax should be same irrespective of whether the invocation-entity is a function pointer or function object.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
1

The standard allows all of the forms you use, but unless you want to confuse readers, it's generally best to be explicit: &f to take the address of the function, and (*p)( x, y ) to call it.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

You can use either form, but it looks most natural (to me) to use this:

p(x, y);
trojanfoe
  • 120,358
  • 21
  • 212
  • 242