任何函数作为模板参数

时间:2013-07-08 07:32:31

标签: c++ templates variadic-functions

#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;
}

我试图弄清楚如何在C ++中将函数(以及,如果可能的话,模板函数)绑定为模板参数。

目前我不知道这是否可能。

这里的一个踢球者是功能签名保证是相似的。

编辑:感谢@sehe和@Potatoswatter,我当前的解决方案就是:http://ideone.com/0jcbUi。会在适当的时候写出答案。

3 个答案:

答案 0 :(得分:6)

我建议让编译器担心在适当的时候解析函数签名。 http://ideone.com/ZeLt1E(代码包含在下方)。

如果你需要调整重载集或多态接口,我建议你也看一下BOOST_PHOENIX_ADAPT_FUNCTION。

编辑回复评论:这是一个演示如何直接使用功能指针和/或指针到成员函数作为函数参数的演示。这是另一种极端方法: http://ideone.com/120Ezs

完整代码

#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;
}

答案 1 :(得分:3)

只是观察您没有或想要运行时状态。部分来自您在C ++聊天室中的评论的推断。

功能没有唯一类型。如果你想生成一个捕获应该调用函数的唯一类型,请使用类模板来执行此操作。

template< typename t, t v >
struct constant {
    typedef t type;
    static constexpr t value = v;

    operator t () { return v; }
};

这与std::integral_constant基本相同,但会从名称中删除integral以避免混淆。 (实际上我只使用std::integral_constant进行了测试,如果你想变得更干净,那取决于你。)

现在,您可以为函数提供单独的类型,这些类型是无状态的,默认构造的函子。

typedef constant< decltype( & padd ), padd > padd_type;
typedef constant< decltype( & psub ), psub > psub_type;

padd_type()( 2, 3 ); // prints 5

请注意,无状态lambdas可转换为函数指针并与此类系统兼容,但您需要明确指定函数指针类型。仅decltype不会让你到那里。

答案 2 :(得分:0)

感谢Potatoswatter和他在C ++休息室的帮助,在这里,我已经为我的问题制定了解决方案。

#include <iostream>
#include <functional>

template <typename func_t, func_t func>
struct Foo {
    template <typename... Arguments>
        void execute(Arguments... args) {
                func(args ...);
        }
};

template <typename T, typename func_t, func_t func>
struct FooMember {
        T member;

        FooMember(T member) : member(member) {}

        template <typename... Arguments>
        void execute(Arguments... args) {
                std::function<void(T&, Arguments ...)> f(func);
                f(this->member, args ...);
        }
};

struct Bar {
        int z;

        Bar(int z) : z(z) {}
        void add(int x, int y) { std::cout << x + y + z << std::endl; }
};

void padd(int x, int y, int z) { std::cout << x + y + z << std::endl; }

int main() {
        auto a = Foo<decltype(&padd), &padd>();
        auto b = FooMember<Bar, decltype(&Bar::add), &Bar::add>(Bar(2));

        a.execute(4, 5, 6); // prints 4+5+6 : 15
        b.execute(4, 5); // prints 4+5+a.z : 4+5+2 : 11

        return 0;
}