35
#include <functional>

struct A
{
    int func(int x, int y)
    {
        return x+y;
    }
};

int main()
{

    typedef std::function<int(int, int) > Funcp;
    A a;
    //Funcp func = std:::bind(&A::func, &a);
    Funcp func = std::bind(&A::func, a, std::placeholders::_1);


    return 0;
}

I am getting errors in both of the above bind functions:

 error C2825: '_Fty': must be a class or namespace when followed by '::'

Where is the syntax error? I am using visual studio 2010

hidayat
  • 9,493
  • 13
  • 51
  • 66
  • 1
    You need a _2 as well as _1 but that doesn't appear to be the error you are getting. Is the correct header for placeholders being included? – CashCow Mar 01 '11 at 11:58
  • it worked after the _2 variable – hidayat Mar 01 '11 at 12:02
  • I wish compilers would give proper errors. That was the obvious error but it wasn't obvious what the compiler was saying. – CashCow Mar 01 '11 at 12:20

2 Answers2

38
Funcp func = 
    std::bind(&A::func, &a, std::placeholders::_1, std::placeholders::_2);
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
ltjax
  • 15,837
  • 3
  • 39
  • 62
  • 2
    It might not matter whether you pass in a as an object or a pointer to bind, it allows both. It might matter of course in the case where the pointer, which is to a local variable, is going to be dangling by the time it gets called. – CashCow Mar 01 '11 at 11:57
  • 2
    @hidayat the placeholders are a magic object that allow you to bind the parameter into them. _1 indicates the first parameter and _2 the second to the function. – CashCow Mar 01 '11 at 11:59
  • ok, and these are only necessary when binding member variables? – hidayat Mar 01 '11 at 12:01
  • 4
    They are necessary if you want to "pass-thru" parameters from the call site of the `std::function`. They allow you to rearrange, duplicate and omit parameters from the call site. In this case, they are placeholders for the parameters you fill into `x` and `y` respectively. – ltjax Mar 01 '11 at 12:07
1

It took a while for me to figure out what's happening. So adding it here for the benefit of others, where an explanation would help. I've renamed some functions and variables for more clarity.

#include <functional>

struct A
{
    int MemberFunc(int x, int y) 
    {
        return x+y;
    }
};

int main()
{
    typedef std::function<int(int, int)> OrdinaryFunc;
 
    A a;
    OrdinaryFunc ofunc = std::bind(&A::MemberFunc, a, std::placeholders::_1, std::placeholders::_2);

    int z = ofunc(10, 20); // Invoke like an ordinary function
 
    return 0;
}

Class member functions have an implicit/hidden parameter which points to the object (this pointer). These member functions can be invoked only by providing an object, which makes it different from an ordinary function.

std::bind can be used to "convert" a member function into an ordinary function by passing the object (pointer or reference). It has be the first argument in the list of args (&a or a in this case) following the member function. In the new function, the object is bound to the implicit/hidden parameter of the member function, and need not be passed when invoked. The unbound arguments are represented by the placeholders _1, _2 and have to be passed when invoked.

ap-osd
  • 2,624
  • 16
  • 16
  • Any idea why half the answers use '&a' in their std::bind and yours uses 'a'? I've only been able to get the 'a' version to work. I.e. std::bind(&fn, a, _1,..) – skyfire Aug 31 '21 at 22:18
  • The object can be either a pointer `&a` or reference `a`, both should work. Check the compiler and version for any limitation(s) it may have. – ap-osd Sep 08 '21 at 14:33
  • 1
    https://godbolt.org/z/bxqbenjqd – Marek R Feb 08 '22 at 09:44