I know that this is simple code, but I can't find amazingly detailed documentation anywhere for the project or on C++'s bind. This is the code:
uri.canonize(bind(&FaceController::onCanonizeSuccess, this, _1, onSuccess, onFailure, uri),
bind(&FaceController::onCanonizeFailure, this, _1, onSuccess, onFailure, uri),
m_ioService, TIME_ALLOWED_FOR_CANONIZATION);
I've only ever used bind with one more argument than the bound function, not with two. Additionally, uri.canonize
has this function signature:
void
FaceUri::canonize(const CanonizeSuccessCallback& onSuccess,
const CanonizeFailureCallback& onFailure,
boost::asio::io_service& io, const time::nanoseconds& timeout) const
And much further down the rabbit hole, onSuccess
and onFailure
do get called with one argument, but I don't think it's important to show all that here. Finally, the function signature for onCanonizeSuccess
is:
void
FaceController::onCanonizeSuccess(const FaceUri& uri,
const CommandSuccessCallback& onSuccess,
const CommandFailureCallback& onFailure,
const FaceUri& request)
Really I'm just asking for someone to interpret this with me. Here's what I have understood:
uri.canonize
is being passed 4 arguments:
FaceController::onCanonizeSuccess
, with the first arg bound to the uri
object, the second arg passed to the bound function, then onSuccess
, onFailure
, and uri
.FaceController::onCanonizeFailure
.m_ioService
TIME_ALLOWED_FOR_CANONIZATION
So what this means is that FaceUri::canonize
here is being passed two function objects that each take 1 argument, and two other things. Then, when FaceUri::canonize
ultimately calls its onSuccess
with that one argument, since that function object is bound to a return type of FaceController::onCanonizeSuccess
, that's the function that will be called.
That's my best attempt at understanding what's going on here. The only issue is that FaceController::onCanonizeSuccess
isn't the bound function. It can't be, because the arity here means we're calling bind
with a return type, and this
is the function to bind to. What is this
in this context? The top-most calling function? uri
? uri.canonize
? This is all as clear as mud. Unfortunately, I don't know which bind we're using, but I believe it is std::bind, since I see a using std::bind clause a few includes up.
So,
void FaceUri::canonize
is a function, which gets called. It accepts four arguments, being (with proper cv and ref qualifiers)
CanonizeSuccessCallback
- a function, which gets called (guessing from the name, on success)
CanonizeFailureCallback
- a function, which gets called (guessing from the name, on failure)
and two plain arguments, you probably understand.
Now, Canonize*Callback
are probably objects (guessing templates), which supposes, to have proper operator()
defined on them. I suppose you know the basics behind std::bind
.
And uri.canonize
is a function call, where first two arguments are functions, to be called when canonizing succeeds or fails.
According to onCanonizeSuccess
singature, you have to pass four parameters to std::bind
for that function. Well, actually, since that function is not static, it requires fifth (or rather null-th) argument of type FaceController*
on which should the function (onCanonizeSuccess
) be called.
bind(
&FaceController::onCanonizeSuccess, // non-static member function requiring first argument to be pointer to FaceController instance
this, // pointer to FaceController instance, that means, the object with function, where uri.canonize is called.
_1, // actually std::placeholders::_1, meaning, that first argument will be passed when calling bound function
onSuccess, // rest of parameters
onFailure,
uri
)