Boost.Bind - понимание заполнителей - PullRequest
7 голосов
/ 20 сентября 2010

Я пытаюсь понять следующий пример, который похож (но не равен) тому, который был опубликован ранее на SO Помогите понять аргументы boost :: bind placeholder :

#include <boost/bind.hpp>
#include <functional>

struct X {
    int value;
};

int main() {    
    X a = { 1 };
    X b = { 2 };

    boost::bind(std::less<int>(),
        boost::bind(&X::value, _1),
        boost::bind(&X::value, _2))
    (a, b);
}

Как это возможно, что самая внешняя функция связывания знает, что она должна передать первый аргумент второму связыванию (который ожидает _1), а второй аргумент третьему связыванию (который ожидает _2)?Я вижу это так, что сначала проверяются внутренние связыватели, поэтому они становятся двумя унарными функциональными объектами, которые позже передаются в связыватель объекта less<int>.И когда вновь созданный функциональный объект вызывается с двумя объектами, a переходит к первой внутренней привязке, а b переходит ко второму.Если бы я был прав, мы бы использовали _1 дважды.Я должен быть не прав.Я повторю свой вопрос еще раз, чтобы прояснить мою проблему: как внешний связующий элемент знает, какой заполнитель был использован, в каком внутреннем связующем?

1 Ответ

7 голосов
/ 20 сентября 2010

аргументы упаковываются в кортеж (a, b) и передаются функторам.тогда внутренний функтор решает, какой элемент кортежа ему нужен, например, try:

boost::bind(&X::value, _1)(a,b)
boost::bind(&X::value, _2)(a,b)

В более общем смысле каждое значение, независимо от того, является ли оно константным, / ссылка / местозаполнитель представляется как функтор, который принимает аргумент кортеж и возвращает значение.1004 *

bind(f, 10)(a) // still functor which discards arguments

Теперь я не уверен на сто процентов, как это делает связывание.тем не менее, именно так Phoenix реализует свою функциональность.если вы пытаетесь понять механизм реализации bind / lambda, посмотрите на phoenix, он очень расширяемый и имеет отличную документацию.

...