Search code examples
c++c++11stdbind

What the heck does std::bind(x, y) do?


I'm stuck reading the description of std::bind in N3225, in subsection 20.8.10.1. It says the following should print 1, but I thought that bind is supposed to copy its arguments and therefor it should print 0. If one wants to refer to the passed argument, one needs to use std::ref, right?

void f(int &a) { a = 1; }

int main() {
  int a = 0;
  std::bind(f, a)();
  std::cout << a << std::endl;
}

GCC outputs 0, agreeing with what I thought things work. But N3225 says that std::bind(f, a1) shall return a call wrapper that when called by wrapper() will call INVOKE(f, v1), where v1 shall be a (the argument I passed in, in other words, using binds's incoming parameter which is a perfect forwarding parameter, std::forward<A1>(a1)).

INVOKE(f, a) is defined by 20.8.2 to f(a). So, this defines that the call to the returned call wrapper passes the original argument. What am I missing?


Solution

  • Wow, this is confusing beyond belief. It defines v1 as tid and it as the following (ti is the i-th perfect forwarding bind parameter, and TiD is the decayed type of that parameter - i.e an array becomes a pointer etc).

    tid is an lvalue of type TiD constructed from std::forward<Ti>(ti)

    Alright, I did say, this tid is std::forward<Ti>(ti) and it's an lvalue! But this is not what it really means to say. It means

    tid is an lvalue of type TiD that refers to an object constructed from std::forward<Ti>(ti)

    It makes much more sense now. Because what if std::forward<Ti>(ti) is actually an rvalue? The "lvalue ... constructed from ..." is meant to mean that we create a new object from "..." and make the lvalue refer to it.