Morgan
Morgan

Reputation: 486

Bind std::function error

I face a problem when trying to bind a method with std::function and std::bind.

In my CommunicationService class :

this->httpServer->BindGET(std::bind(&CommunicationService::ManageGETRequest, this, std::placeholders::_1));

CommunicationService::ManageGetRequest signature :

MessageContent CommunicationService::ManageGetRequest(std::string uri, MessageContent msgContent)

BindGET signature :

void RESTServer::BindGET(RequestFunction getMethod)

RequestFunction typedef :

typedef std::function<MessageContent(std::string, MessageContent)> RequestFunction;

The error on BindGET :

error C2664: 'void RESTServer::BindGET(RequestFunction)': cannot convert argument 1 from 'std::_Binder < std::_Unforced,MessageContent (__cdecl communication::CommunicationService::* )(std::string,MessageContent),communication::CommunicationService *const ,const std::_Ph < 1 > & >' to 'RequestFunction'

Before, my RequestFunction was like that :

typedef std::function<void(std::string)> RequestFunction;

and it worked perfectly. (with all signature methods adjusted of course).

I don't understand what causes the error.

Upvotes: 3

Views: 3846

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275260

Change

this->httpServer->BindGET(
  std::bind(&CommunicationService::ManageGETRequest, this, std::placeholders::_1)
);

to

this->httpServer->BindGET(
  [this](std::string uri, MessageContent msgContent) {
    this->ManageGETRequest(std::move(uri), std::move(msgContent));
  }
);

Using std::bind is almost always a bad idea. Lambdas solve the same problems, and almost always do it better, and give better error messages. The few cases where std::bind has features lambdas do not where mostly covered by C++14.

std::bind was written in pre-lambda C++11 as boost::bind then brought into the standard at the same time lambdas where. At the time, lambdas had a few limitations, so std::bind made sense. But this isn't one of the cases where lambdas C++11 limitations occur, and as lambda has grown in power since, learning to use std::bind has significantly diminished marginal utility at this point.

Even if you master std::bind, it has enough annoying quirks (like passing a bind expression to bind) that avoiding it has payoff.

You could also fix it with:

this->httpServer->BindGET(
  std::bind(&CommunicationService::ManageGETRequest, this, std::placeholders::_1, std::placeholders::_2)
);

but I don't think you should.

Upvotes: 10

Related Questions