如何结合std :: bind(),可变参数模板和完美的转发? [英] How to combine std::bind(), variadic templates, and perfect forwarding?

查看:2168
本文介绍了如何结合std :: bind(),可变参数模板和完美的转发?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过第三方函数从另一个方法调用方法;但都使用可变参数模板。例如:

  void third_party(int n,std :: function< void(int)> f)
{
f(n);
}

struct foo
{
模板< typename ... Args>
void invoke(int n,Args& ... args)
{
auto bound = std :: bind(& foo :: invoke_impl& this,
std :: placeholders :: _ 1,std :: forward< Args>(args)...);

third_party(n,bound);
}

template< typename ... Args>
void invoke_impl(int,Args&& ...)
{
}
};

foo f;
f.invoke(1,2);问题是,我收到一个编译错误:








$ b

  / usr / include / c ++ / 4.7 / functional:1206:35:error:can not bind'int'lvalue to'int&&'

我尝试使用lambda,但也许 GCC 4.8不处理语法;这里是我尝试:

  auto bound = [this,& args ...](int k){invoke_impl k,std :: foward< Args>(args)...) }; 

我得到以下错误:

 错误:expected','before'...'token 
错误:'...'前的期望标识符token
错误:参数包未使用''展开。 ..':
note:'args'



根据我的理解,用类型 int&&& 实例化 invoke_impl ,而我认为使用& ;



在这种情况下,我将会保留实际的参数类型。感谢,

解决方案

绑定到& foo :: invoke_impl& code>将创建一个绑定函数,它接受一个 Args&& 参数,意味着一个右值。问题是传递的参数将是一个 lvalue ,因为参数存储为一些内部类的成员函数。



通过将& foo :: invoke_impl< Args ...> 更改为& foo :: invoke_impl< Args& 。> 所以成员函数将采用一个左值。

  auto bound = std :: bind (& foo :: invoke_impl< Args& ...>,this,
std :: placeholders :: _ 1,std :: forward< Args>(args)...)

这里是演示


I want to invoke a method from another, through a third-party function; but both use variadic templates. For example:

void third_party(int n, std::function<void(int)> f)
{
  f(n);
}

struct foo
{
  template <typename... Args>
  void invoke(int n, Args&&... args)
  {
    auto bound = std::bind(&foo::invoke_impl<Args...>, this,
                           std::placeholders::_1, std::forward<Args>(args)...);

    third_party(n, bound);
  }

  template <typename... Args>
  void invoke_impl(int, Args&&...)
  {
  }
};

foo f;
f.invoke(1, 2);

Problem is, I get a compilation error:

/usr/include/c++/4.7/functional:1206:35: error: cannot bind ‘int’ lvalue to ‘int&&’

I tried using a lambda, but maybe GCC 4.8 does not handle the syntax yet; here is what I tried:

auto bound = [this, &args...] (int k) { invoke_impl(k, std::foward<Args>(args)...); };

I get the following error:

error: expected ‘,’ before ‘...’ token
error: expected identifier before ‘...’ token
error: parameter packs not expanded with ‘...’:
note:         ‘args’

From what I understand, the compiler wants to instantiate invoke_impl with type int&&, while I thought that using && in this case would preserve the actual argument type.

What am I doing wrong? Thanks,

解决方案

Binding to &foo::invoke_impl<Args...> will create a bound function that takes an Args&& parameter, meaning an rvalue. The problem is that the parameter passed will be an lvalue because the argument is stored as a member function of some internal class.

To fix, utilize reference collapsing rules by changing &foo::invoke_impl<Args...> to &foo::invoke_impl<Args&...> so the member function will take an lvalue.

auto bound = std::bind(&foo::invoke_impl<Args&...>, this,
                       std::placeholders::_1, std::forward<Args>(args)...);

Here is a demo.

这篇关于如何结合std :: bind(),可变参数模板和完美的转发?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆