10

I am trying to compile the following code taken from here but I am getting a compile error. Does anyone have any ideas what might be wrong?

The code

#include <iostream>
#include <functional>

struct Foo {
    Foo(int num) : num_(num) {}
    void print_add(int i) const { std::cout << num_+i << '\n'; }
    int num_;
};


int main()
{
    // store a call to a member function
    std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
    Foo foo(314159);
    f_add_display(foo, 1);
}

The compile error :

Error   1   error C2664: 'std::_Func_class<_Ret,_V0_t,_V1_t>::_Set' : 
cannot convert parameter 1 from '_Myimpl *' to 'std::_Func_base<_Rx,_V0_t,_V1_t> *' 

Thanks.

Barış Uşaklı
  • 13,440
  • 7
  • 40
  • 66
  • 1
    @jogojapan: `print_add` takes two arguments, it has an _implicit_ `this` argument of type `Foo const*` as well. – K-ballo Oct 27 '12 at 00:39
  • @K-ballo: `std::function` automatically uses `std::mem_fn` if its first parameter type is a (reference / pointer to the) class type of the member. – Xeo Oct 27 '12 at 00:45
  • Looks like a standard library bug to me, I suggest submitting a bug report at [MS Connect](https://connect.microsoft.com/VisualStudio/) and posting the link here so we can upvote it. (This is a clear regression since your code compiles cleanly in VC++ 2010.) – ildjarn Oct 27 '12 at 00:55
  • I know you're using VC++, but just FYI, your example works fine with g++-4.8. Whatever the problem is, it might be specific to visual studio. – Nate Kohl Oct 27 '12 at 00:58
  • If it is working in g++ 4.8 then it is definitely an issue with VS. Making a bug report. – Barış Uşaklı Oct 27 '12 at 01:00
  • 3
    @ildjarn Here is the bug report https://connect.microsoft.com/VisualStudio/feedback/details/768899/std-function-not-compiling-in-vs2012. If someone else tries to compile it in VS2012 and gets the same result let me know. I would like to rule out the possibility that my installation is broken. – Barış Uşaklı Oct 27 '12 at 01:01
  • 1
    @Barış : I tested in VC++ 2010 and VC++ 2012 – the former was fine, the latter was not. – ildjarn Oct 27 '12 at 01:16
  • I'm getting the same problem (compiling my own code). Looks like a bug in VS2012 to me. The same code worked fine in VS2010. – Alex Korban Oct 27 '12 at 06:50

1 Answers1

7

This looks like a bug in VS2012, I have made a bug report here.

For now the following works :

Edit: edited based on Xeo's suggestion to use std::mem_fn

#include <iostream>
#include <functional>

struct Foo {
    Foo(int num) : num_(num) {}
    void print_add(int i) const { std::cout << num_+i << '\n'; }
    int num_;
};

int main()
{
    // store a call to a member function
    std::function<void(const Foo&, int)> f_add_display = std::mem_fn(&Foo::print_add);
    Foo foo(314159);
    f_add_display(foo, 1);
}
Barış Uşaklı
  • 13,440
  • 7
  • 40
  • 66
  • 2
    Your code is kinda strange. You bind `foo` and still have a `std::function`. The only reason this works is because `std::bind` swallows unneeded arguments. The correct equivalent thing to what you're trying in the question would be using `std::mem_fn(&Foo::print_add)`. – Xeo Oct 29 '12 at 03:16
  • @Xeo when should one use std::bind vs std::mem_fn? std::mem_fn looks simpler. – Barış Uşaklı Oct 29 '12 at 04:11
  • `std::mem_fn` is a simple wrapper for member pointers that returns a function object which takes a pointer or reference to the class as its first parameter and every parameter from a member function (if any) after that. `std::bind` is for binding arguments to a function. – Xeo Oct 29 '12 at 05:40
  • 7
    Note that for those who use 2013, I actually able to reproduce the same error even though it has been submitted for 2012. I hope someone else can confirm this too. –  Oct 30 '13 at 12:15