【问题标题】:C++ function call wrapper with class member function as template argument [closed]使用类成员函数作为模板参数的 C++ 函数调用包装器[关闭]
【发布时间】:2019-08-04 21:18:48
【问题描述】:

我尝试使用this 代码,但它不适用于类成员函数。有没有办法为类成员函数生成一个包装器并将其称为非类成员的包装器?

#include <functional>
template <typename F>
class wrapper;

template <typename F, typename... Args>
typename std::result_of<F(Args...)>::type execute_helper (F&& f, Args&&... args) {
    return std::forward<F>(f)( std::forward<Args>(args)...);
}

template<typename Ret, typename... Args>
class wrapper <std::function<Ret(Args...)>>
{
    std::function<Ret(Args...)> m_f;
public:
    wrapper( std::function<Ret(Args...)> f ): m_f(f) {}
    Ret operator()(Args... args) const  { 
        return execute_helper (m_f, args...); 
    }
};

【问题讨论】:

  • 为什么还需要execute_helper?只需写出m_f(args...)。另外,为什么这不适用于成员函数(您得到的确切错误是什么,以及产生该错误的代码段)?这个包装器做了哪些std::function 没有做的事情?

标签: c++ templates variadic-templates variadic-functions


【解决方案1】:

成员函数的问题是他们需要调用类的对象。

假设你可以将类的对象连同指向成员函数的指针一起传递给构造函数,我想你可以编写如下的包装器

template <typename Ret, typename Cl, typename ...Args>
class wrapper <Ret(Cl::*)(Args...)>
 {
   private:
      std::function<Ret(Args...)> m_f;

   public:
      wrapper (Cl cl, Ret(Cl::*m)(Args...))
         : m_f{ [=](Args... as) mutable { return (cl.*m)(as...); } }
          { }

      Ret operator() (Args... args) const
       { return m_f(args...); }
 };

以下是完整的可编译使用示例

#include <functional>
#include <iostream>

template <typename F>
class wrapper;

template <typename Ret, typename Cl, typename ...Args>
class wrapper <Ret(Cl::*)(Args...)>
 {
   private:
      std::function<Ret(Args...)> m_f;

   public:
      wrapper (Cl cl, Ret(Cl::*m)(Args...))
         : m_f{ [=](Args... as) mutable { return (cl.*m)(as...); } }
          { }

      Ret operator() (Args... args) const
       { return m_f(args...); }
 };

struct foo
 {
   long long bar (int a, long b, long long c)
    { return a+b+c; }
 };

int main ()
 {
   foo  f;

   wrapper<decltype(&foo::bar)>  wfb{f, &foo::bar};

   std::cout << wfb(1, 2l, 3ll) << std::endl;
 }

请注意,该示例适用于非 const 成员函数。

对于 const 成员函数,您可能需要另一个包装器

template <typename Ret, typename Cl, typename ...Args>
class wrapper <Ret(Cl::*)(Args...) const>
 {
   private:
      std::function<Ret(Args...)> m_f;

   public:
      wrapper (Cl const & cl, Ret(Cl::*m)(Args...) const)
         : m_f{ [=](Args... as) { return (cl.*m)(as...); } }
          { }

      Ret operator() (Args... args) const
       { return m_f(args...); }
 };

在这两种情况下,您都可以稍微改进operator() 添加完美转发

  template <typename ... As>   
  Ret operator() (As && ... as) const
   { return m_f(std::forward<As>(as)...); } 

【讨论】:

  • 有没有办法修改此代码以在类定义中使用它?
  • @TwaikYont - 抱歉...我不明白你的意思。
  • 我需要在 *.hpp 的类定义中使用包装器。
  • 类似于 A 类的东西:public B { wrapper foo(&B::foo); } 。我尝试使用带有占位符的 std::mem_fn 和 std::bind 编写代码,但失败了。
  • @TwaikYont - 我想这是可能的;但是,在我的示例中,您还需要一个 B 类型的对象来初始化包装器。
猜你喜欢
  • 2016-07-29
  • 2017-03-10
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2016-06-25
  • 2010-11-03
  • 2011-07-06
相关资源
最近更新 更多