Vishal Kumar
Vishal Kumar

Reputation: 802

std::bind not working as expected

std::vector<int> v1;
std::function<void(const int&)> funct = 
static_cast<std::function<void(const int&)>>(std::bind(
                                            &std::vector<int>::push_back,
                                            &v1,
                                            std::placeholders::_1));

This gives me no matching function for call to bind.

I am able to do this though:

threadPool.push_back(std::thread(runThread<lazyFunct>,
                     std::bind(&LazySkipList<int>::add,
                     &lsl, std::placeholders::_1), 0, 1000000, 1000000));

I am using Xcode 4.4 with llvm C++11 support.

Upvotes: 3

Views: 1823

Answers (2)

Jesse Good
Jesse Good

Reputation: 52365

Try:

auto funct = std::bind(static_cast<void(std::vector<int>::*)(const int&)>
                                             (&std::vector<int>::push_back),
                                              &v1,
                                              std::placeholders::_1);

push_back is overloaded, so you need to cast it to the proper overload.

Or:

void(std::vector<int>::*p)(const int&) = &std::vector<int>::push_back;
auto funct = std::bind(p, &v1, std::placeholders::_1);

Or explicitly provide the template argument as shown in Keith Ballard's answer which might be the best actually.

Upvotes: 1

Lily Ballard
Lily Ballard

Reputation: 185671

The problem is std::vector::push_back() is overloaded with the two possible type signatures:

void push_back(const T& value);
void push_back(T&& value);

As such, the template parameter to std::bind() cannot be inferred. However, you can declare the template parameter explicitly:

std::bind<void(std::vector<int>::*)(const int&)>(&std::vector<int>::push_back, &v1, std::placeholders::_1);

This resolves correctly.

Of course, at this point it might be simpler just to use a lambda:

auto func = [&](int i){ v1.push_back(i); };

Upvotes: 7

Related Questions