13

I need something that is the opposite of std::bind, that adds dummy parameters to a function signature instead of how boost::bind binds parameters away.

e.g. I have this function:

std::function<void (void)> myFunc;

But I want to convert it into a std::function<void(int)> to pass into this function

void processFunction( std::function<void(int)> func);

2 Answers2

6

Edit Oh, I mentioned the obvious in chat:

@EthanSteinberg: lambdas?

[] (int realparam, int dummy) { return foo(realparam); }

But it was dismissed, which is why I jump to:

Edit I just realized a much simpler approach: http://ideone.com/pPWZk

#include <iostream>
#include <functional>
using namespace std::placeholders;

int foo(int i)
{
    return i*2;
}

int main(int argc, const char *argv[])
{
    std::function<int(int, int)> barfunc = std::bind(foo, (_1, _2));
    std::cout << barfunc(-999, 21) << std::endl;

    // or even (thanks Xeo)
    barfunc = std::bind(foo, _2);
    std::cout << barfunc(-999, 21) << std::endl;
}

Variadic Templates http://ideone.com/8KIsW

A somewhat longer answer based on variadic templates would result in possibly smaller code at the call site (if you wanted to wrap functions with a long argument list).

#include <iostream>
#include <functional>

int foo(int i)
{
    return i*2;
}

template <typename Ax, typename R, typename... A>
struct Wrap
{
    typedef R (*F)(A...);
    typedef std::function<R(A...)> Ftor;

    Wrap(F f) : _f(f) { }
    Wrap(const Ftor& f) : _f(f) { }

    R operator()(Ax extra, A... a) const
    { return _f(a...); /*just forward*/ }

    Ftor _f;
};

template <typename Ax=int, typename R, typename... A>
std::function<R(Ax, A...)> wrap(R (f)(A...))
{
    return Wrap<Ax,R,A...>(f);
}

template <typename Ax=int, typename R, typename... A>
std::function<R(Ax, A...)> wrap(std::function<R(A...)> functor)
{
    return Wrap<Ax,R,A...>(functor);
}

int main(int argc, const char *argv[])
{
    auto bar = wrap(foo);
    std::function<int(int, int)> barfunc = wrap(foo);

    std::cout << barfunc(-999, 21) << std::endl;

    // wrap the barfunc?
    auto rewrap = wrap(barfunc);
    std::cout << rewrap(-999, -999, 21) << std::endl;

    return 0;
}

Generalizing from this would require some more heavy lifting. I think I've seen in the past helpers to 'dissect' (using meta-programming) the signature of a std::function<> and you should be able to make it recognize non-void functions, and perhaps even adding a parameter at the end or in the middle (tricky, as far as I can tell now).

But for your simple case from the OP, it looks like you're covered

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Brainwave led to much simpler approach – sehe Dec 18 '11 at 04:06
  • Reinstated my longer solution (further improved/generalized) because it will be shorter for functions with many arguments. In fact, you might run out of placeholders on such functions. You can now specify the type of the extra argument (`typename Ax`) http://ideone.com/8KIsW – sehe Dec 18 '11 at 13:13
3

You could use a lambda, if your implementation supports it:

processFunction([=](int a){ myFunc(); });
Chris Devereux
  • 5,453
  • 1
  • 26
  • 32