Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any function as a template argument

#include <iostream>

void padd(int a, int b) { std::cout << a + b << std::endl; }
void psub(int a, int b) { std::cout << a - b << std::endl; }

template <??? op>
class Foo {
public:
    template<typename... Arguments>
    void execute(Arguments... args) {
        op(args ...);
    }
};

int main() {
    auto f1 = Foo<padd>();
    f1.execute(5, 6); // ideally would print 11

    auto f2 = Foo<psub>();
    f2.execute(5, 6); // ideally would print -1

    return 0;
}

I am trying to figure out how to bind functions (and, if possible, template functions) as template parameters in C++.

As it stands I am not aware if this is possible.

A kicker here is that the function signatures are not guaranteed to be similar.

edit: thanks to @sehe and @Potatoswatter, my current solution is thus: http://ideone.com/0jcbUi. Will write up answer when appropriate.

like image 289
deceleratedcaviar Avatar asked Jul 08 '13 07:07

deceleratedcaviar


1 Answers

I'd suggest letting the compiler worry about resolving function signatures when appropriate. http://ideone.com/ZeLt1E (code included below).

If you need to adapt overload sets or polymorphic interfaces, I would suggest also looking at BOOST_PHOENIX_ADAPT_FUNCTION.

Edit In response to the comments: Here's a demo of how you could use strictly function-pointers and/or pointer-to-member functions directly as function arguments. This is the other extreme approach: http://ideone.com/120Ezs

Full code

#include <iostream>

template <typename F>
struct Foo {
    Foo(F&& f) : f(std::forward<F>(f)) {}

    template<typename... Arguments>
    void execute(Arguments... args) {
        f(args ...);
    }

  private:
    F f;
};

template <typename F>
  Foo<F> make_foo(F&& f = F()) { return {f}; }

void padd(int a, int b) { std::cout << a + b << std::endl; }
void psub(int a, int b) { std::cout << a - b << std::endl; }

int main() {
    auto f = make_foo(padd);
    f.execute(5, 6);

    make_foo(psub).execute(5, 6);

    return 0;
}
like image 175
sehe Avatar answered Sep 22 '22 18:09

sehe