1

I am trying to make a server by looking at the sample code of cpprestSDK. But I don't know why I bind in the sample code.

Below is the sample code.

stdafx.h

class Handler{
public:
    Handler() {};
    Handler(utility::string_t url);

    pplx::task<void> open() { return m_listener.open(); }
    pplx::task<void> close() { return m_listener.close(); }

private:
    void handle_get(http_request request);
    void handle_put(http_request request);
    void handle_post(http_request request);
    void handle_del(http_request request);
};

hander.cpp

  
#include "stdafx.hpp"

Handler::Handler(utility::string_t url) : m_listener(url)
{

    m_listener.support(methods::GET, std::bind(&Handler::handle_get, this, std::placeholders::_1));
    m_listener.support(methods::PUT, std::bind(&Handler::handle_put, this, std::placeholders::_1));
    m_listener.support(methods::POST, std::bind(&Handler::handle_post, this, std::placeholders::_1));
    m_listener.support(methods::DEL, std::bind(&Handler::handle_del, this, std::placeholders::_1));
}

Looking at the reference for support, it is defined as follows.

void support (const http::method &method, const std::function< void(http_request)> &handler)

I thought I could define it like this:

m_listener.support(methods::GET, &Handler::handle_get);

But it failed.

Can you tell me why I use "this" and "std::placeholders::_1" when doing a bind?

sample code : https://learn.microsoft.com/ko-kr/archive/blogs/christophep/write-your-own-rest-web-server-using-c-using-cpp-rest-sdk-casablanca

cpprestSDK listener reference : https://microsoft.github.io/cpprestsdk/classweb_1_1http_1_1experimental_1_1listener_1_1http__listener.html

Hwan E
  • 566
  • 2
  • 13
  • _"I thought I could define it like this_" - and, if you could, how would the compiler know what instance to call that method on? it can't. that's why binding is required, to create a callable that encapsulates not only the identify of a member but also an instance on which to use it. – underscore_d Sep 01 '20 at 12:34

1 Answers1

5

The member function

void support (const http::method &method,
              const std::function< void(http_request)> &handler)

expects handler to be a callable which has

  • an argument of type http_request
  • a return type void.

A plain function void handle(http_request) would match this required signature.

If you want to register a (non-static) member function this is also possible but you have to provide the object as well (as non-static member functions may not be called without object).

The std::bind(&Handler::handle_get, this, std::placeholders::_1) acts as (a kind of) adapter to fit your member function (with this as bound object) into that requirement.

The std::placeholders::_1 denotes, where to bind the argument (of type http_request) into the wrapped member function call.

A simpler way would be to use a lambda as adapter (instead of the bind):

m_listener.support(methods::GET, [this](http_request http_req) { this->handle_get(http_req); });

or even:

m_listener.support(methods::GET, [this](http_request http_req) { handle_get(http_req); });

Further readings:

JeJo
  • 30,635
  • 6
  • 49
  • 88
Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56