简体   繁体   English

如何boost :: bind以通用引用作为参数的模板成员函数

[英]How to boost::bind a template member function which takes a universal reference as a parameter

I've been trying to use boost::bind to post a call to a member function onto an io_strand but have been getting errors. 我一直在尝试使用boost :: bind将对成员函数的调用发布到io_strand上,但是一直出错。 I have manged to create a simplistic equivalent example of what I am trying to do and have seen the same error in the following context: 我已经设法创建一个我想做的简单的等效示例,并且在以下情况下看到了相同的错误:

I have the following class containing the doThings() member function I want to call: 我有以下包含要调用的doThings()成员函数的类:

class base
{
public:
  int x = 1;

  template<typename B>
  void doThings(B&& b)
  {}
};

There is then a subclass of this (to accurately represent the scenario I am encountering my error - I don't think it makes a difference) 然后有一个子类(以准确表示我遇到错误的情况-我认为这没有什么关系)

class child : public base
{
  int y = 2;
};

I have the following code trying to make the boost::bind call: 我有以下代码尝试进行boost :: bind调用:

template<typename A>
void getInt(child c, A&& a)
{
  boost::bind((void(child::*)(A)) &child::doThings, &c, std::forward<A>(a))();
}

And then this is being called as follows: 然后将其调用如下:

int main()
{
  child c = child();
  getInt(c, 7);
}

When I compile the above code I get the following error: 当我编译上面的代码时,出现以下错误:

error: no matches converting function 'doThings' to type 'void (class child::*)(int)' 错误:没有匹配项将函数'doThings'转换为'void(class child :: *)(int)'


If I change the function signature of doThings() to take a regular B type rather than a universal reference ie B rather than B&& then it compiles a runs with no issues. 如果我将doThings()的函数签名更改为采用常规B类型而不是通用引用(即B而不是B&&则它将编译运行而没有问题。
I suspect my issue is something to with the cast I'm doing in getInt(): 我怀疑我的问题与我在getInt()中执行的强制转换有关:

(void(child::*)(A))

But I don't know what I would need to change it to. 但是我不知道将其更改为什么。 A&& wouldn't work in this context as I believe it would represent an r-value reference in that context. A&&在这种情况下不起作用,因为我认为它将代表该上下文中的r值引用。 The compilation error I get when I try it seems to confirm this: 我尝试时遇到的编译错误似乎证实了这一点:

error: cannot bind 'int' lvalue to 'int&&' 错误:无法将“ int”左值绑定到“ int &&”

For completeness: if I don't attempt to perform a cast then I get the following compilation error: 出于完整性考虑:如果我不尝试执行强制转换,则会收到以下编译错误:

error: no matching function for call to 'bind(unresolved overloaded function type, child*, int)' 错误:没有匹配的函数调用“ bind(未解析的重载函数类型,child *,int)”

Could someone please enlighten me on what I would need to do in order to make my boost::bind call valid in this scenario please? 有人可以给我启发,使我的boost :: bind呼叫在这种情况下有效吗?

I am using C++11 我正在使用C ++ 11

I would suggest against using boost::bind , as lambda expressions can be used to cleanly bind arguments (avoiding many pitfalls of bind explained in this talk by STL ) . 我建议不要使用boost::bind ,因为lambda表达式可用于干净地绑定参数(避免STL本次演讲中解释的bind陷阱)


I'm assuming that you want to: 我假设您要:

  • Capture a by move if an rvalue-reference is passed to getInt . 捕捉a如果右值引用传递到由移动 getInt

  • Capture a by reference if an lvalue-reference is passed to getInt . 如果将左值引用传递给getInt捕获a按引用

I'm also assuming that: 我还假设:

  • A is not int in your real code, otherwise perfect-forwarding would not make sense. A在您的实际代码中不是int ,否则完美转发将毫无意义。

  • You want to avoid unnecessary copies of a or that A could be a move-only type. 您要避免不必要aA可能是仅移动类型的副本。

  • You only have access to C++11 (and not to newer standards) . 您只能访问C ++ 11 (而不能访问较新的标准)

If you need to "perfectly-capture" a (ie capture-by-move if A is an rvalue-reference, capture-by-reference if A is an lvalue-reference) , you need some sort of wrapper. 如果需要“完全捕获” a (即,如果A是右值引用,则按移动捕获;如果A是左值引用,则按引用捕获) ,则需要某种包装。

Unfortunately this is non-trivial , even though it gets better in C++14 and C++17. 不幸的 ,即使在C ++ 14和C ++ 17中变得更好, 这也不是小事 Here's an example of how the final syntax could look: 下面是最终的语法如何看一个例子:

template<typename A>
void getInt(child c, A&& a)
{
    // `a_wrapper` stores an `A&` or an `A` depending on the value category
    // of `a`. Copying it should not copy `a` - it should conditionally move 
    // it depending on the original value category of `a`.
    auto a_wrapper = forward_capture_wrapper(std::forward<A>(a));

    // `forward_like` retains information about `a`'s value category so that
    // it can be used in the body of the lambda to forward the reference/value
    // stored inside `a_wrapper`.
    //                          vvvvvvvvvvvvvvv
    [&a, a_wrapper]{ c.doThings(forward_like<A>(a_wrapper.get()); }();
    //                                          ^^^^^^^^^^^^^^^
    // `a_wrapper.get()` returns a reference that can then be moved or passed
    // to `c.doThings`.
}

As you can see, you need a template function called forward_capture_wrapper that deals with "perfect-capture". 如您所见,您需要一个名为forward_capture_wrapper模板函数来处理“ perfect-capture”。 You can find information on how to implement that in these resources: 您可以在以下资源中找到有关如何实现的信息:

By combining the resources above you should be able to implement a "perfect capture wrapper" in C++11. 通过结合上面的资源,您应该能够在C ++ 11中实现“完美的捕获包装器”。

You also need a forward_like helper function that preserves the original value category of the a argument. 您还需要一个forward_like可以保留的原始值类的辅助功能a说法。 You can find an implementation of that: 您可以找到一个实现:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 专门化一个带有通用引用参数的函数模板 - Specializating a function template that takes a universal reference parameter C++:模板function以function为参数,function以模板类型为参数 - C++: template function taking function which takes another function which takes reference to template type as parameter 如何使用std :: for_each和boost :: bind调用参数的成员函数? - How to call a member function on a parameter with std::for_each and boost::bind? 如何使用boost :: bind正确绑定成员函数 - How to correctly bind a member function with boost::bind C ++ / Boost:将成员函数作为参数传递给boost :: bind - C++/Boost: Passing a member function as a parameter to be used in boost::bind 如何使用boost :: bind将静态成员函数绑定到boost :: function - How to bind a static member function to a boost::function using boost::bind 想要实现以信号类型为参数的升压信号模板 - Want to implement boost like signal template which takes function type as a parameter 如何模拟将对象引用作为参数的函数 - 谷歌测试 - How to mock a function which takes an object reference as parameter - google test 如何推导以引用为参数的函数的返回类型 - How to deduce the return type of a function which takes a reference as parameter std::bind 与可变参数模板成员 function 和通用引用 - std::bind with variadic template member function and universal references
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM