可以在参数C ++中使用任何类成员的通用函数

时间:2014-12-14 15:34:18

标签: c++ c++11

我有几个关于类方法的测试。我很难使用std :: function。 这是一个简化问题的示例代码:

#include <iostream>
#include <functional>

template<typename T>
struct Foo
{
    Foo(T sum) : sum_(sum) {};
    Foo<T> method_one(const Foo<T>& foo) const { Foo<T> res(sum_ + foo.sum_); return res; }
    Foo<T> method_two(const Foo<T>& foo) const { Foo<T> res(sum_ + foo.sum_ + 10); return res; }
    Foo<T> method_three(const Foo<T>& foo, T val) const { Foo<T> res(sum_ + foo.sum_ + val); return res;}
    friend std::ostream &operator << (std::ostream & output, const Foo &foo) { output << foo.sum_; return output;}

    T sum_;
};

template<typename T>
void do_the_work(const Foo<T>& a, const Foo<T>& b, const std::function<Foo<T>(const Foo<T>&)> &func)
{
    // I do stuff before [...]
    Foo<T> c = a.func(b);
    std::cout << c << std::endl;
    // I do stuff after [...]
}

int main()
{
    Foo<float> a(1.0);
    Foo<float> b(2.0);


    // I would like to replace this
    Foo<float> c = a.method_two(b);
    std::cout << c;  // 1 + 2 + 10


    // with something like that
    do_the_work(a, b, a.method_one);
    do_the_work(a, b, a.method_two);
    // and if possible make it more generic...
    do_the_work(a, b, a.method_three, 12);
}

我尝试在main()中使用bind但没有成功:

std::function<Foo<float>(const Foo<float>&)> f = std::bind(&Foo<float>::method_one, &a);

任何其他优雅的解决方案都会很好。您可以注意到这是为了防止代码冗余并多次执行“在之前或之后执行操作”

2 个答案:

答案 0 :(得分:2)

您缺少成员函数的隐式this参数,您必须在std::function签名中指定它:

template<typename T>
void do_the_work(const Foo<T>& a, const Foo<T>& b, std::function<Foo<T>(const Foo<T>&, const Foo<T>&)> func)
{
    Foo<T> c = func(a, b);
    ...
}

请注意std::function是如何被调用的(它不是a.foo(b)

并称之为:

do_the_work<float>(a, b, &Foo<float>::method_one);
do_the_work<float>(a, b, &Foo<float>::method_two);

如果你想/可以绑定将调用你的函数的对象:

template<typename T>
void do_the_work_binded(const Foo<T>& b, std::function<Foo<T>(const Foo<T>&)> func)
{
    // I do stuff before [...]
    Foo<T> c = func(b);
    std::cout << c << std::endl;
    // I do stuff after [...]
}

...

std::function<Foo<float>(const Foo<float>&)> fb = std::bind(&Foo<float>::method_one, a, std::placeholders::_1);
do_the_work_binded(b, fb);

<强> Live demo

答案 1 :(得分:2)

我在std::function的签名中跳过使用do_the_work并在内部解决所有内容。它使得包含更多参数更容易:

template<typename T, typename Func, typename... Args>
void do_the_work(const Foo<T>& a,
                 const Foo<T>& b,
                 Func func,
                 Args&&... args)
{ 
  auto f = std::bind(func, a, b, std::forward<Args>(args)...);

  // I do stuff before [...]
  Foo<T> c = f();
  std::cout << c << std::endl;
  // I do stuff after [...]
}

以后

do_the_work(a, b, &decltype(a)::method_one);
do_the_work(a, b, &decltype(a)::method_two);
// and if possible make it more generic...
do_the_work(a, b, &decltype(a)::method_three, 12);