简体   繁体   中英

std::bind with variadic template member function and universal references

Here i have small piece of code and it compiles and works just fine (at least with my GCC 7.3.0 and Ubuntu 18.04):

#include <functional>
#include <string>
#include <iostream>

void func(int a, const std::string& b, const std::string& c)
{
  std::cout << a << b << c << std::endl;
}

class Test
{
public:
  template <typename ... ARGS>
  bool func_to_bind(ARGS&& ... args) const {
    func(args...);
    return true;
  }

  template <typename ... ARGS>
  void binding_func(ARGS&& ... args) const 
  {
    auto func_obj = std::bind(&Test::func_to_bind<int&, ARGS&...>, this, 42, args...);
    func_obj();
  }
};


int main()
{
  Test obj;
  obj.binding_func(std::string("one"), std::string("two"));
}

The part that i don't understand is this line:

std::bind(&Test::func_to_bind<int&, ARGS&...>, this, 42, args...);

Why does compiler require to use references as template type parameters? If i remove reference from int like this:

std::bind(&Test::func_to_bind<int, ARGS&...>, this, 42, args...);

It won't compile. Also if i change func_to_bind signature to this:

bool func_to_bind(ARGS& ... args) const

It will compile just fine even with missing reference. Could anyone explain what's exactly going on here? I also did some search and found this question: How to combine std::bind(), variadic templates, and perfect forwarding?

But i don't completely understand the answer.

If you specify the template argument as int explicitly, then the parameter type of func_to_bind would become int&& , ie an rvalue-reference type. Note that the stored arguments are passed to the invokable object as lvalue s bystd::bind :

Otherwise, the ordinary stored argument arg is passed to the invokable object as lvalue argument:

The lvalue can't be bound to the rvalue-referece parameter then invocation fails.

If you specify the template argument as int& explicitly, then the parameter type of func_to_bind becomes int& , ie an lvalue-reference type; lvalue could be bound to lvalue-reference then it works fine.

And if you change the parameter type of func_to_bind to ARGS& , it'll be always an lvalue-reference, for the same reason above it'll work fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM