6

I'm trying to call an overloaded function which operates on function pointers that have parameters with default values.

void originalFunction1 (int a = 0) {printf("I'm #1 and a is %d",a);}
void originalFunction2 () {printf("I'm #2");}

void overloadedFunction (void (*fptr)(void))
{
  fptr();
}

void overloadedFunction (void (*fptr)(int))
{
  overloadedFunction( (void(*)(void)) fptr);
}

int main() 
{
  overloadedFunction(originalFunction1);
  overloadedFunction(originalFunction2);

  // output is:
  // I'm #1 an a is -1073743272
  // I'm #2
}

As the answers to this question points out, default values are not part of the function signature and also can't be repeated during the (function pointer -) parameter definition. As my example shows, they can be cast away for calling, but they will then not be initialized to their default value.

Is there any way to work around this?

I can't modify the original function but I know the default value. I can modify both the main overloaded function as well as the redirects. The fptr's will always only be called without parameters. In reality, there are more overloaded functions as also the return type differs, but I can cast that away more easily.

Community
  • 1
  • 1
Chaos_99
  • 2,284
  • 2
  • 25
  • 29

1 Answers1

2

The short answer is no. The cast is legal, but the only thing you can do with the results is to cast them back to the orginal type. Default arguments do not change the signature of the function. They only enter into account at the call site, where they are passed if the client doesn't provide an argument. The function itself is always called with the full set of arguments, which it clearly won't be if you call it through the results of the cast.

The usual answer here, if you have control of the sources, is to use overloading instead of default arguments. (I have heard arguments that you should always use overloading instead of default arguments.) So

void originalFunction1( int a ) { ... }
void originalFunction1() { originalFunction1( 0 ); }

instead of what you have.

Alternatively, you might be able to play games with templates:

template <typename FunctionPtr>
void overloadedFunction( FunctionPtr fptr )
{
    fptr();
}

I'd prefer the first solution if you can use it, however.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • `The cast is legal` ... is that correct? I believe calling a function with a different typecast is an undefined behavior. The cast can be used only for storing a function pointer. – iammilind Feb 14 '13 at 08:57
  • @iammilind: That's pretty much what he said. :) – Dolda2000 Feb 14 '13 at 09:00
  • I could maybe combine this with the comment from _Tony The Lion_ on the original question: If I add another parameter to the main overloaded function telling it the default value, I could re-cast the function pointer to its original signature and call it with the submitted value. – Chaos_99 Feb 14 '13 at 09:57
  • @Chaos_99 That would be a possible solution, but if you have control over the sources, the simplest solution is simply to replace the default argument with an overload. Otherwise, you can play tricks with templates. I've edited my answer with examples of each. – James Kanze Feb 14 '13 at 11:56
  • @iammilind That's exactly what I said. Given `void f( int )`, `reinterpret_cast( f )` is perfectly legal and well defined (and portable, despite the `reinterpret_cast`). On the other hand the **only** thing you can do with the resulting pointer is cast it back to a `void (*)( int )`. Trying to call a function through it is undefined behavior. – James Kanze Feb 14 '13 at 11:59