6

Possible Duplicate:
how to specify a pointer to an overloaded function?

I have a library which has a class defined as:

struct ClassA
{
    static ClassA foo(long);
    static ClassA foo(double);
}

I need to get the addresses of both of those functions. The code I am currently trying gives error C2440: cannot convert from 'overloaded-function' to '...'

ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;

I thought it might be the fact that they are static, but placing static either before or after the return type gives the same error.

Community
  • 1
  • 1
Austin Wagner
  • 1,072
  • 1
  • 17
  • 30
  • Do you even need class specifiers on static methods? Member methods OK, but I wonder if it's any different than pointing to a "free function" than to a static method? – Kevin Anderson Aug 31 '12 at 18:09
  • I'd have thought it was just `ns::ClassA (*name)(long) = &ns::ClassA::foo;` and `ns::ClassA (*name)(double) = &ns::ClassA::foo;` and then the compiler would work out which you wanted. – hcarver Aug 31 '12 at 18:09
  • @Hbcdev That worked. If you write that up as an answer I will accept it. Imaginary bonus points if you explain why that fixed it. The code I have up there works just fine if the functions are not static. – Austin Wagner Aug 31 '12 at 18:25
  • Since there doesn't seem to be any way to PM, I'll just say here that this is NOT an exact duplicate. The answers to the other question would not have helped me and the answer to this question does not answer the question this is a supposed duplicate of. – Austin Wagner Aug 31 '12 at 20:37

3 Answers3

6

The fact that the function is overloaded is not really relevant. The real issue here is the difference between a function-pointer and a member-function-pointer. I'll run through some examples without overloading.

Solution: Either remove the static, in order to define them as member-functions. Or else replace ns::ClassA::*ClassA_foo1 with *ClassA_foo1. I think you want the latter. (But I actually recommend you use typedef, as others have already suggested).

Consider these two:

namespace ns {
struct ClassA
{
    static ClassA foo(long);
};
}

and

namespace ns {
struct ClassA
{
    ClassA foo(long);
};
}

In the former case, foo is static and is therefore a typical function, and can be stored in a function-pointer:

ns::ClassA (ClassA_foo1)(long) = &ns::ClassA::foo;

If you remove the static, then it is not a function any more, it's a member function. And pointers-to-member-functions are different from pointers-to-functions, they must be executed with an object that will be the this object on which the method is called.

The type of a function pointer includes the type of the return value and the type of the parameters. But the type of a pointer-to-member-function must also include the type of the this object - you wouldn't expect to be able to run a method from a Circle on an object of type BankAccount.

Declaring a pointer-to-function:

 ReturnType (*variable_name) (PARAM1, PARAM2)

Declaring a pointer-to-member-function:

 ReturnType (ThisObjectType::*variable_name) (PARAM1, PARAM2)

This last line is the interesting one. At first glance, you might think that R (A::*v) (P1,P2) declares a normal function-pointer and places the resulting variable v into the A scope. But it does not. Instead it defines a pointer-to-member-function which operates on objects of type A.

Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88
4

The problem that you are observing has absolutely nothing to do with the fact that the function is overloaded. You'd get the same error for a non-overloaded function.

Static member functions have ordinary function type. Meanwhile, you are trying to interpret them as functions of member-function type. This leads to pointer type mismatch reported to you by the compiler. Here's a simple example that will fail to compile for the very same reason

struct S {
  static void foo();
};
...
void (S::*p)() = &S::foo; // ERROR, pointer type mismatch

In other words, your pointers are declared as pointers of pointer-to-member-function type. Such pointers cannot hold the address of a static member function. A static member function and a non-static member function are beasts of completely different nature. The corresponding pointer types are not compatible and not convertible to each other. That's the reason for your error.

This is how it was probably supposed to look

ns::ClassA (*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (*ClassA_foo2)(double) = &ns::ClassA::foo;

i.e. the pointers on the left-hand side should be declared as ordinary function pointers, not as member function pointers.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
0
ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;

It looks like you are trying to set the pair of static members ClassA_foo1 and ClassA_foo2 at file scope. If so, this is not valid syntax. The syntax for defining a static member is

SomeType ClassName::member = initializer;

It's best to use a typedef to declare and define ClassA_foo1 and ClassA_foo2:

struct ClassA {
   typedef ClassA (*ClassALongGenerator) (long);
   typedef ClassA (*ClassADoubleGenerator) (double);

   static ClassALongGenerator ClassA_foo1;
   static ClassADoubleGenerator ClassA_foo2;
};

then at file scope in some source file

ns::ClassALongGenerator ClassA_foo1 = ns::ClassA::foo;
ns::ClassADoubleGenerator ClassA_foo2 = ns::ClassA::foo;
David Hammen
  • 32,454
  • 9
  • 60
  • 108