7
#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。会在适当的时候写出答案。

4

3 回答 3

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;
}
于 2013-07-08T07:39:26.473 回答
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

请注意,无状态 lambda 可以转换为函数指针并且与这样的系统兼容,但您需要明确指定函数指针类型。decltype一个人不会让你到达那里。

于 2013-07-08T08:10:54.000 回答
0

感谢 Potatoswatter 和 sehe 在 C++ Lounge 和这里​​的帮助,我已经为我的问题制定了解决方案。

#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;
}
于 2013-07-22T07:43:14.120 回答