cageman
cageman

Reputation: 333

how to pass both function pointers and lambda's using one interface

I am trying to use function pointers and lambdas together using one interface. I decided to use std::function, but I quickly found out that it cannot deal with overloaded functions by itself.

Example:

void foobar(double i_double ){std::cout << "double argument" << i_double << std::endl;}
void foobar(){std::cout << "no argument" << std::endl;}
void foobar(int){std::cout << "int argument" << std::endl;}

std::function<void(double)> func = static_cast<void(*)(double)>(&foobar);

This code only compiles by using a static_cast. Since at our company we have quite a lot of overloaded functions this is too much of a hassle. For now I decided to implement two interfaces: One for std::function objects and another one for function pointers, although I would really like to just wrap the function pointers in a std::function object as well (without additional code on the calling side).

Any "nice" solution to this problem?

edit: The way I will be using it is part of a large framework, but boils down to the code below. I hope the following code below makes the use case clear.

namespace
{
    bool IsAllowed(string) {...}
    bool IsAllowed(int) {...}
}

CIteratorFilter<String>( listofstrings, IsAllowed );

CSomeObject object;
CIteratorFilter<String>( listofstrings, 
    [&object](String i_string ) { return object.IsAllowed( i_string ); } 
);

Currently this CIteratorFilter needs to implement both the function pointer and std::function interface, which is not really nice in my opinion.

Upvotes: 1

Views: 59

Answers (3)

iammilind
iammilind

Reputation: 70030

Use C++11 features with macro-magic.

#define FUNCTION(RETURN, NAME, ...) \
  std::function<RETURN (__VA_ARGS__)>(static_cast<RETURN(*)(__VA_ARGS__)>(&NAME))

Usage:

auto func1 = FUNCTION(void, foobar, double);
auto func2 = FUNCTION(void, foobar);
auto func3 = FUNCTION(void, foobar, int);

If you don't want to use variable argument then below is an alternate way of doing it:

#define FUNCTION(RETURN, NAME, PARAMETERS) \
  std::function<RETURN PARAMETERS>(static_cast<RETURN(*)PARAMETERS>(&NAME))

Usage:

auto func1 = FUNCTION(void, foobar, (double));
auto func2 = FUNCTION(void, foobar, ());
auto func3 = FUNCTION(void, foobar, (int));

Upvotes: 0

bolov
bolov

Reputation: 75815

See... an XY problem.

This or anything similar is not needed:

std::function<void(double)> func = static_cast<void(*)(double)>(&foobar);

You need to use templates:

template <class Func>
CIteratorFilter<String>( listofstrings, Func func) {
  // call func whatever it may be function pointer, lambda, callable object:
  func(..whatever params...);
}

you can use perfect fowarding for func if you want

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409356

Why not use a non-capturing lambda with the correct argument and that calls the foobar function?

Like

std::function<void(double)> func = [](double d){ foobar(d); };

That's the nicest I can think of.

Upvotes: 0

Related Questions