使用shared_from_this生成仿函数

时间:2017-04-26 11:02:21

标签: c++ shared-ptr variadic-templates

我想从继承自enable_shared_from_this的类A创建一个仿函数,就像这样的类:

class A: public std::enable_shared_from_this<A> {
    ...
}

我想要一个看起来像这样的成员函数(错误的代码):

template <typename Args...>
std::function<void(Args ...)> functor_from_this(void (A::*method)(Args...)) {
    return std::bind(method, shared_from_this());
}

上面的代码会产生一些错误,从warning C4180: qualifier applied to function type has no meaning; ignored开始,这让我怀疑我是以错误的方式解决这个问题。我如何实现这样的目标?

(a)将Args绑定到仿函数的额外学分,因此我得到一个签名为void fn()的函数,以及(b)在继承自的一般用途类中执行所有这些操作enable_shared_from_this<T>

2 个答案:

答案 0 :(得分:3)

好吧,对于C ++ 14,解决方案是easy enough to write。只是放弃std::bind并返回一个lambda:

#include <memory>
#include <iostream>
#include <functional>

struct A: std::enable_shared_from_this<A> {

    template <typename... Args>
    std::function<void(Args...)> functor_from_this(void (A::*method)(Args...)) {
        return [=, obj = shared_from_this()](Args... args) {
          ((*obj).*method)(args...);
        };
    }

    void foo(int) { std::cout << "foo" << '\n'; }
    void bar() { std::cout << "bar" << '\n'; }
};

int main()
{
  auto a = std::make_shared<A>();

  auto f = a->functor_from_this(&A::foo);
  auto b = a->functor_from_this(&A::bar);

  f(1);
  b();
}

对于C ++ 11,正如Jarod42在评论中指出的那样,使用一个更简单的中间变量:

#include <memory>
#include <iostream>
#include <functional>

struct A: std::enable_shared_from_this<A> {

    template <typename... Args>
    std::function<void(Args...)> functor_from_this(void (A::*method)(Args...)) {
        auto obj = shared_from_this();
        return [=](Args... args) {
          ((*obj).*method)(args...);
        };
    }

    void foo(int) { std::cout << "foo" << '\n'; }
    void bar() { std::cout << "bar" << '\n'; }
};

int main()
{
  auto a = std::make_shared<A>();

  auto f = a->functor_from_this(&A::foo);
  auto b = a->functor_from_this(&A::bar);

  f(1);
  b();
}

答案 1 :(得分:1)

对于额外的功劳(B),这是我找到的解决方案,基于StoryTeller&amp;的答案。贾罗德:

#include <memory>
#include <iostream>
#include <functional>

template <class T>
class enable_functor_from_this: public std::enable_shared_from_this<T> {
    public:
    template <typename... Args>
    decltype(auto) functor_from_this(void (T::*method)(Args...)) {
        auto obj = this->shared_from_this();
        return [=](Args... args) {
          ((*obj).*method)(args...);
        };
    }
};

struct A: enable_functor_from_this<A> {
    void foo(int) { std::cout << "foo" << '\n'; }
    void bar() { std::cout << "bar" << '\n'; }
};

int main()
{
  auto a = std::make_shared<A>();

  auto f = a->functor_from_this(&A::foo);
  auto b = a->functor_from_this(&A::bar);

  f(1);
  b();
}