Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Chapter 1. Boost.Bind

Boost , Chapter 1. Boost.Bind ,

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Chapter 1. Boost.Bind

Распространяется по лицензииBoost Software License, версия 1.0.

<boost::bind>является обобщением стандартных функций<std::bind1st>и<std::bind2nd>. Он поддерживает произвольные функциональные объекты, функции, указатели функций и указатели функций членов и способен связывать любой аргумент с конкретным значением или маршрутом входных аргументов в произвольные позиции.<bind>не предъявляет никаких требований к объекту функции; в частности, ему не нужны<result_type>,<first_argument_type>и<second_argument_type>стандартные типдефы.

Учитывая эти определения:

int f(int a, int b)
{
    return a + b;
}
int g(int a, int b, int c)
{
    return a + b + c;
}

<bind(f,1,2)>будет производить «нулевой» функциональный объект, который не принимает аргументов и возвращает<f(1,2)>. Так же<bind(g, 1,2,3)()>эквивалентно<to g(1,2,3)>.

Выборочно можно связать только некоторые аргументы.<bind(f,_1, 5)(x)>эквивалентно<f(x,5)>; здесь<_1>—заполнительаргумент, который означает «заменить первым входным аргументом».

Для сравнения, вот та же операция, выраженная со стандартными библиотечными примитивами:

std::bind2nd(std::ptr_fun(f), 5)(x);

<bind>охватывает также функциональность<std::bind1st>:

std::bind1st(std::ptr_fun(f), 5)(x);   // f(5, x)
bind(f, 5, _1)(x);                     // f(5, x)

<bind>может обрабатывать функции с помощью более чем двух аргументов, и его механизм замены аргументов более общий:

bind(f, _2, _1)(x, y);                 // f(y, x)
bind(g, _1, 9, _1)(x);                 // g(x, 9, x)
bind(g, _3, _3, _3)(x, y, z);          // g(z, z, z)
bind(g, _1, _1, _1)(x, y, z);          // g(x, x, x)

Обратите внимание, что в последнем примере объект функции, произведенный<bind(g,_1, _1,_1)>, не содержит ссылок на какие-либо аргументы, кроме первого, но он все еще может использоваться с более чем одним аргументом. Любые дополнительные аргументы молча игнорируются, как первый и второй аргумент игнорируются в третьем примере.

Аргументы, которые<bind>принимает, копируются и удерживаются внутренним объектом возвращаемой функции. Например, в следующем коде:

int i = 5;
bind(f, i, _1);

копия значения<i>хранится в объекте функции.<boost::ref>и<boost::cref>можно использовать для того, чтобы объект функции сохранял ссылку на объект, а не копию:

int i = 5;
bind(f, ref(i), _1);
bind(f, cref(i), _1);

<bind>не ограничивается функциями; принимает произвольные функциональные объекты. В общем случае тип возврата генерируемого функционального объекта<operator()>должен быть определен явно (без оператора<typeof>тип возврата не может быть выведен):

struct F
{
    int operator()(int a, int b) { return a - b; }
    bool operator()(long a, long b) { return a == b; }
};
F f;
int x = 104;
bind<int>(f, _1, _1)(x);		// f(x, x), i.e. zero

Некоторые компиляторы имеют проблемы с синтаксисом<bind<R>(f,...)>. По причинам переносимости поддерживается альтернативный способ выражения вышеизложенного:

boost::bind(boost::type<int>(), f, _1, _1)(x);

Обратите внимание, однако, что альтернативный синтаксис предоставляется только в качестве обходного пути. Он не является частью интерфейса.

Когда объект функции показывает вложенный тип, названный<result_type>, явный тип возврата может быть опущен:

int x = 8;
bind(std::less<int>(), _1, 9)(x);	// x < 9

[Примечание:Возможность опустить тип возврата доступна не на всех компиляторах.

По умолчанию<bind>делает копию предоставленного функционального объекта.<boost::ref>и<boost::cref>могут использоваться для хранения ссылки на объект функции, а не на копию. Это может быть полезно, когда объект функции не является копируемым, дорогим для копирования или содержит состояние; конечно, в этом случае ожидается, что программист гарантирует, что объект функции не будет уничтожен, пока он все еще используется.

struct F2
{
    int s;
    typedef void result_type;
    void operator()(int x) { s += x; }
};
F2 f2 = { 0 };
int a[] = { 1, 2, 3 };
std::for_each(a, a+3, bind(ref(f2), _1));
assert(f2.s == 6);

Указатели на функции-члены и указатели на члены данных не являются функциональными объектами, поскольку они не поддерживают<operator()>. Для удобства<bind>принимает указатели-члены в качестве своего первого аргумента, и поведение таково, как если бы<boost::mem_fn>использовался для преобразования указателя-члена в объект функции. Другими словами, выражение

bind(&X::f, args)

является эквивалентным

bind<R>(mem_fn(&X::f), args)

где<R>- тип возврата<X::f>(для функций члена) или тип члена (для членов данных).

[Примечание:<mem_fn>создает функциональные объекты, которые способны принять указатель, ссылку или умный указатель на объект в качестве первого аргумента; для получения дополнительной информации см. документацию<mem_fn>

Пример:

struct X
{
    bool f(int a);
};
X x;
shared_ptr<X> p(new X);
int i = 5;
bind(&X::f, ref(x), _1)(i);		// x.f(i)
bind(&X::f, &x, _1)(i);			// (&x)->f(i)
bind(&X::f, x, _1)(i);			// (internal copy of x).f(i)
bind(&X::f, p, _1)(i);			// (internal copy of p)->f(i)

Последние два примера интересны тем, что они производят «самосодержащиеся» функциональные объекты.<bind(&X::f,x, _1)>хранит копию<x>.<bind(&X::f,p, _1)>хранит копию<p>, и поскольку<p>является<boost::shared_ptr>, объект функции сохраняет ссылку на свой экземпляр<X>и будет оставаться в силе даже тогда, когда<p>выходит за рамки или является<reset()>.

Некоторые из аргументов, переданных<bind>, могут быть вложенысами связывают выражения:

bind(f, bind(g, _1))(x);               // f(g(x))

Внутренниесвязывающие выраженияоцениваются в неуказанном порядке перед внешним<bind>при вызове функционального объекта; затем результаты оценки заменяются на их место при оценке внешнего<bind>. В приведенном выше примере, когда объект функции вызывается с помощью списка аргументов<(x)>,<bind(g, _1)(x)>сначала оценивается, получая<g(x)>, а затем<bind(f,g(x))(x)>оценивается, получая конечный результат<f(g(x))>.

Эта особенность<bind>может быть использована для выполнения функциональной композиции. См.bind_as_compose.cppдля примера, который демонстрирует, как использовать<bind>для достижения аналогичной функциональностиBoost.Compose.

Обратите внимание, что первый аргумент - объект связанной функции - не оценивается, даже если это объект функции, который производится аргументом<bind>или, поэтому приведенный ниже пример не работает так, как ожидалось:

typedef void (*pf)(int);
std::vector<pf> v;
std::for_each(v.begin(), v.end(), bind(_1, 5));

Желаемый эффект может быть достигнут посредством объекта функции помощника<apply>, который применяет свой первый аргумент в качестве объекта функции к остальной части своего списка аргументов. Для удобства, реализация<apply>предусмотрена вфайле заголовка application.hpp. Вот как выглядит модифицированная версия предыдущего примера:

typedef void (*pf)(int);
std::vector<pf> v;
std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5));

Хотя первый аргумент по умолчанию не оценивается, все остальные аргументы являются. Иногда необходимо не оценивать аргументы, следующие за первым, даже когда они вложены, связывают подвыражения. Это может быть достигнуто с помощью другого функционального объекта,<protect>, который маскирует тип так, что<bind>не распознает и не оценивает его. При вызове защитите просто перенаправьте список аргументов на другой неизмененный объект функции.

Заголовокprotect.hppсодержит реализацию<protect>. Для<protect>объекта функции связи из оценки используйте<protect(bind(f,...))>.

Для удобства объекты функции, создаваемые<bind>, перегружают логический, а не оператор<!>и реляционный и логический операторы<==, !=,<, <=,>, >=,&&, ||>.

<!bind(f, ...)>эквивалентно<bind(logical_not(),bind(f, ...))>, где<logical_not>является функциональным объектом, который принимает один аргумент<x>и возвращает<!x>.

<bind(f,...) opx>, гдеopявляется реляционным или логическим оператором, эквивалентно<bind(relation(),bind(f, ...),x)>, где<relation>является функциональным объектом, который принимает два аргумента<a>и<b>и возвращает<aopb>.

На практике это означает, что вы можете легко отрицать результат<bind>:

std::remove_if(first, last, !bind(&X::visible, _1)); // remove invisible objects

Сравните результат<bind>со значением:

std::find_if(first, last, bind(&X::name, _1) == "Peter");
std::find_if(first, last, bind(&X::name, _1) == "Peter" || bind(&X::name, _1) == "Paul");

:

bind(&X::name, _1) == _2

или против другогосвязывающего выражения:

std::sort(first, last, bind(&X::name, _1) < bind(&X::name, _2)); // sort by name
class image;
class animation
{
public:
    void advance(int ms);
    bool inactive() const;
    void render(image & target) const;
};
std::vector<animation> anims;
template<class C, class P> void erase_if(C & c, P pred)
{
    c.erase(std::remove_if(c.begin(), c.end(), pred), c.end());
}
void update(int ms)
{
    std::for_each(anims.begin(), anims.end(), boost::bind(&animation::advance, _1, ms));
    erase_if(anims, boost::mem_fn(&animation::inactive));
}
void render(image & target)
{
    std::for_each(anims.begin(), anims.end(), boost::bind(&animation::render, _1, boost::ref(target)));
}
class button
{
public:
    boost::function<void()> onClick;
};
class player
{
public:
    void play();
    void stop();
};
button playButton, stopButton;
player thePlayer;
void connect()
{
    playButton.onClick = boost::bind(&player::play, &thePlayer);
    stopButton.onClick = boost::bind(&player::stop, &thePlayer);
}

Как правило, объекты функции, порожденные<bind>, берут свои аргументы за основу и, следовательно, не могут принимать временные или буквальные константы. Это неотъемлемое ограничение языка C++ в его нынешнем (2003) воплощении, известное как проблема пересылки. (Это будет исправлено в следующем стандарте, обычно называемом C++0x.)

Библиотека использует подписи формы

template<class T> void f(T & t);

принимать аргументы произвольных типов и передавать их на немодифицированные. Как уже отмечалось, это не работает с неконстными r-значениями.

На компиляторах, поддерживающих частичную упорядоченность шаблонов функций, возможно решение добавить перегрузку:

template<class T> void f(T & t);
template<class T> void f(T const & t);

К сожалению, это требует 512 перегрузок для девяти аргументов, что непрактично. Библиотека выбирает небольшое подмножество: для двух аргументов она обеспечивает перегрузку const в полном объеме, для удобств трех и более она обеспечивает одну дополнительную перегрузку со всеми аргументами, взятыми ссылкой const. Это охватывает разумную часть случаев использования.

Вероятно, потому, что вы использовали общий синтаксис<bind<R>(f,...)>, тем самым инструктируя<bind>не «инспектировать» f для обнаружения ошибок типа arity и return.

Первая форма предписывает<bind>проверить тип<f>, чтобы определить его аритмию (количество аргументов) и тип возврата. Ошибки Arity будут обнаружены в «связанное время». Этот синтаксис, конечно, предъявляет некоторые требования<f>. Это должна быть функция, указатель функции, указатель функции члена или объект функции, который определяет вложенный тип, названный<result_type>; короче говоря, это должно быть что-то, что<bind>может распознать.

Вторая форма предписывает<bind>не пытаться распознать тип<f>. Обычно он используется с функциональными объектами, которые не выставляют или не могут выставлять<result_type>, но также может использоваться с нестандартными функциями. Например, текущая реализация не распознает автоматически функции с переменными аргументами, такие как<printf>, поэтому вам придется использовать<bind<int>(printf,...)>. Обратите внимание, что альтернативный<bind(type<R>(),f,...)>синтаксис поддерживается по причинам переносимости.

Другим важным фактором, который следует учитывать, является то, что компиляторы без частичной специализации шаблона или поддержки частичного упорядочивания шаблона функции не могут обрабатывать первую форму, когда<f>является объектом функции, и в большинстве случаев не будут обрабатывать вторую форму, когда<f>является функцией (указателем) или указателем функции члена.

Да, если вы<#define BOOST_BIND_ENABLE_STDCALL>. Альтернативой является рассмотрение функции какобщего функционального объектаи использование синтаксиса<bind<R>(f,...)>.

Да, если вы<#define BOOST_BIND_ENABLE_PASCAL>. Альтернативой является рассмотрение функции какобщего функционального объектаи использование синтаксиса<bind<R>(f,...)>.

Иногда. На некоторых платформах указатели на внешние функции «С» эквивалентны «обычным» указателям функций, поэтому они работают нормально. Другие платформы рассматривают их как разные типы. Ожидается, что реализация<bind>, ориентированная на конкретную платформу, будет решать проблему прозрачно; эта реализация этого не делает. Как обычно, обходной путь состоит в том, чтобы рассматривать функцию какобщий объект функциии использовать синтаксис<bind<R>(f,...)>.

Непортативные расширения, как правило, должны по умолчанию отключаться, чтобы предотвратить блокировку поставщика. Если бысоответствующие макросыбыли определены автоматически, вы могли бы случайно воспользоваться ими, не понимая, что ваш код, возможно, больше не переносим. Кроме того, некоторые компиляторы имеют возможность сделать<__stdcall><__fastcall>своим стандартом вызова по умолчанию, и в этом случае отдельная поддержка не потребуется.

В выражении<bind(f,a1,a2, ...,aN)>объект функции<f>должен иметь возможность принимать ровно N аргументов. Эта ошибка обычно обнаруживается в «связанное время»; другими словами, ошибка компиляции сообщается в строке, где<bind()>вызывается:

int f(int, int);
int main()
{
    boost::bind(f, 1);    // error, f takes two arguments
    boost::bind(f, 1, 2); // OK
}

Распространенным вариантом этой ошибки является забывание о том, что функции-члены имеют неявный аргумент «это»:

struct X
{
    int f(int);
}
int main()
{
    boost::bind(&X::f, 1);     // error, X::f takes two arguments
    boost::bind(&X::f, _1, 1); // OK
}

Как и в обычных вызовах функции, связанный объект функции должен быть совместим со списком аргументов. Несовместимость обычно обнаруживается компилятором во время вызова, и результатом обычно является ошибка<bind.hpp>в строке, которая выглядит как:

return f(a[a1_], a[a2_]);

Пример такой ошибки:

int f(int);
int main()
{
    boost::bind(f, "incompatible");      // OK so far, no call
    boost::bind(f, "incompatible")();    // error, "incompatible" is not an int
    boost::bind(f, _1);                  // OK
    boost::bind(f, _1)("incompatible");  // error, "incompatible" is not an int
}

Заполнитель<_N>выбирает аргумент в позиции<N>из списка аргументов, прошедшего в «время вызова». Конечно, попытка выйти за пределы этого списка является ошибкой:

int f(int);
int main()
{
    boost::bind(f, _1);                  // OK
    boost::bind(f, _1)();                // error, there is no argument number 1
}

Ошибка обычно сообщается в<bind.hpp>, в строке, аналогичной:

return f(a[a1_]);

При эмуляции<std::bind1st(f,a)>распространенной ошибкой этой категории является тип<bind(f,a,_2)>вместо правильного<bind(f, a,_1)>.

Форма<bind(f,a1,a2, ...,aN)>вызывает автоматическое распознавание типа<f>. Он не будет работать с произвольными функциональными объектами;<f>должен быть функцией или указателем функции члена.

Можно использовать эту форму с функциональными объектами, определяющими<result_type>, но только на компиляторах, поддерживающих частичную специализацию и частичную упорядоченность. В частности, MSVC до версии 7.0 не поддерживает этот синтаксис для функциональных объектов.

Форма<bind<R>(f,a1,a2, ...,aN)>поддерживает произвольные функциональные объекты.

Можно (но не рекомендуется) использовать эту форму с функциями или указателями функций членов, но только на компиляторах, поддерживающих частичную упорядоченность. В частности, MSVC до версии 7.0 не полностью поддерживает этот синтаксис для функций и указателей функций членов.

По умолчанию<bind(f,a1,a2, ...,aN)>формараспознает «обычные» функции C++ и указатели функций.Функции, использующие другую конвенцию вызовов, или функции с переменными аргументами, такие как<std::printf>, не работают. Общая<bind<R>(f,a1,a2, ...,aN)>формаработает с нестандартными функциями.

На некоторых платформах внешние функции «С», такие как<std::strcmp>, не распознаются короткой формой<bind>.

См. также<__stdcall>и<pascal>Поддержка.

Попытка связать перегруженную функцию обычно приводит к ошибке, поскольку нет способа определить, какая перегрузка должна быть связана. Это общая проблема с функциями-членами с двумя перегрузками, как в этом упрощенном примере:

struct X
{
    int& get();
    int const& get() const;
};
int main()
{
    boost::bind(&X::get, _1);
}

Двусмысленность может быть решена вручную, отбрасывая указатель функции (члена) на желаемый тип:

int main()
{
    boost::bind(static_cast< int const& (X::*) () const >(&X::get), _1);
}

Другой, возможно, более читаемой альтернативой является введение временной переменной:

int main()
{
    int const& (X::*get) () const = &X::get;
    boost::bind(get, _1);
}

Объекты функций, которые производятся<bind>, не моделируют понятия STLУнарная функцияилиБинарная функция, даже когда объекты функций являются унарными или двоичными операциями, потому что типы объектов функций не имеют общедоступных типовых значений<result_type>и<argument_type>или<first_argument_type>и<second_argument_type>. Однако в тех случаях, когда эти типдефы желательны, функция полезности<make_adaptable>может быть использована для адаптации объектов унарной и двоичной функций к этим понятиям. Это позволяет комбинировать объекты унарных и двоичных функций, полученные из<bind>, с шаблонами STL, такими как<std::unary_negate>и<std::binary_negate>.

Функция<make_adaptable>определена в<<boost/bind/make_adaptable.hpp>>, которая должна быть включена в дополнение к<<boost/bind.hpp>>:

#include <boost/bind/make_adaptable.hpp>
template <class R, class F> unspecified-type make_adaptable(F f);
template<class R, class A1, class F> unspecified-unary-functional-type make_adaptable(F f);
template<class R, class A1, class A2, class F> unspecified-binary-functional-type make_adaptable(F f);
template<class R, class A1, class A2, class A3, class F> unspecified-ternary-functional-type make_adaptable(F f);
template<class R, class A1, class A2, class A3, class A4, class F> unspecified-4-ary-functional-type make_adaptable(F f);

Этот пример показывает, как использовать<make_adaptable>, чтобы сделать предикат для «не является пространством»:

typedef char char_t;
std::locale loc("");
const std::ctype<char_t>& ct = std::use_facet<std::ctype<char_t> >(loc);
auto isntspace = std::not1(boost::make_adaptable<bool, char_t>(boost::bind(&std::ctype<char_t>::is, &ct, std::ctype_base::space, _1)));

В этом примере<bind>создаётся «пространство» (унитарный) предикат. Затем он передается<make_adaptable>так, что функция объекта моделирует.Унарная функцияможет быть создана как аргумент<std::not1>.

Некоторые компиляторы, в том числе MSVC 6.0 и Borland C++ 5.5.1, имеют проблемы с подписями функций верхнего уровня<const>:

int f(int const);
int main()
{
    boost::bind(f, 1);     // error
}

Обратная сторона: убрать<const>квалификатор из аргумента.

На MSVC (до версии 7.0), когда<boostbind>приведен в действие с помощью декларации:

using boost::bind;

Синтаксис<bind<R>(f,...)>не работает. Обратная сторона: либо используйте квалифицированное имя<boost::bind>, либо используйте вместо этого директиву использования:

using namespace boost;

На MSVC (до версии 7.0) вложенный шаблон класса под названием<bind>будет затенять шаблон функции<boost::bind>, нарушая синтаксис<bind<R>(f,...)>. К сожалению, некоторые библиотеки содержат вложенные шаблоны классов, названные<bind>(по иронии судьбы, такой код часто является специфическим обходным путем MSVC).

Для этого используется альтернативный синтаксис<bind(type<R>(),f,...)>.

MSVC (до версии 7.0) рассматривает эллипс в переменной функции аргумента (например,<std::printf>) как тип. Поэтому он примет (неправильную в текущей реализации) форму:

bind(printf, "%s\n", _1);

Отклонить правильную версию:

bind<int>(printf, "%s\n", _1);
namespace boost
{
// no arguments
template<class R, class F> unspecified-1 bind(F f);
template<class F> unspecified-1-1 bind(F f);
template<class R> unspecified-2 bind(R (*f) ());
// one argument
template<class R, class F, class A1> unspecified-3 bind(F f, A1 a1);
template<class F, class A1> unspecified-3-1 bind(F f, A1 a1);
template<class R, class B1, class A1> unspecified-4 bind(R (*f) (B1), A1 a1);
template<class R, class T, class A1> unspecified-5 bind(R (T::*f) (), A1 a1);
template<class R, class T, class A1> unspecified-6 bind(R (T::*f) () const, A1 a1);
template<class R, class T, class A1> unspecified-6-1 bind(R T::*f, A1 a1);
// two arguments
template<class R, class F, class A1, class A2> unspecified-7 bind(F f, A1 a1, A2 a2);
template<class F, class A1, class A2> unspecified-7-1 bind(F f, A1 a1, A2 a2);
template<class R, class B1, class B2, class A1, class A2> unspecified-8 bind(R (*f) (B1, B2), A1 a1, A2 a2);
template<class R, class T, class B1, class A1, class A2> unspecified-9 bind(R (T::*f) (B1), A1 a1, A2 a2);
template<class R, class T, class B1, class A1, class A2> unspecified-10 bind(R (T::*f) (B1) const, A1 a1, A2 a2);
// implementation defined number of additional overloads for more arguments
}
namespace
{
 unspecified-placeholder-type-1 _1;
 unspecified-placeholder-type-2 _2;
 unspecified-placeholder-type-3 _3;
// implementation defined number of additional placeholder definitions
}

Всенеопределенные-Nтипы, возвращаемые<bind>, являютсяCopyConstructible.неопределенные-N<::result_type>определяется как тип возвратанеопределенные-N<::operator()>.

Все типынеуказанных держателей-NявляютсяCopyConstructible. Их конструкторы копий не бросают исключений.

Функция μ<(x,v1, v2,...,vm)>, где<m>является неотрицательным целым числом, определяется как:

  • <x.get()>, когда<x>относится к типу<boost::reference_wrapper><<T>>для некоторого типа<T>;
  • <vk>, когда<x>является (копией) заполнителя_kдля некоторого положительного целого числаk;
  • <x(v1,v2,...,vm)>, когда<x>является (копией) функционального объекта, возвращаемого<bind>;
  • <x>В противном случае.
template<class R, class F> unspecified-1 bind(F f)
  • Возврат:Объект функции λ такой, что выражение λ<(v1,v2,...,vm)>эквивалентно<f()>, неявно преобразовано в<R>.
  • Броски:Ничего, если копировщик<F>не бросает исключение.
template<class F> unspecified-1-1 bind(F f)
  • Эффекты:эквивалентно<bind<typename F::result_type, F>(f)>.
  • Примечания:Осуществления допускаются для вывода о типе возврата<f>с помощью других средств в качестве расширения без использования элемента<result_type>.
template<class R> unspecified-2 bind(R (*f) ())
  • Возвращает:Объект функции λ такой, что выражение λ<(v1,v2,...,vm)>эквивалентно<f()>.
  • Бросает:Ничего.
template<class R, class F, class A1> unspecified-3 bind(F f, A1 a1)
  • Возвращение:Объект функции λ такой, что выражение λ<(v1,v2,...,vm)>эквивалентно<f(>μ<(a1,v1,v2,...,vm))>, неявно преобразовано в<R>.
  • Броски:Ничего, кроме того, что создатели копий<F>или<A1>не делают исключения.
template<class F, class A1> unspecified-3-1 bind(F f, A1 a1)
  • Эффекты:эквивалентно<bind<typename F::result_type, F, A1>(f,a1)>.
  • Примечания:Осуществления допускаются для вывода о типе возврата<f>с помощью других средств в качестве расширения без использования элемента<result_type>.
template<class R, class B1, class A1> unspecified-4 bind(R (*f) (B1), A1 a1)
  • Возврат:Объект функции λ такой, что выражение λ<(v1,v2,...,vm)>эквивалентно<f(>μ<(a1,v1,v2,...,vm))>.
  • Броски:Ничего, если копирайтер<A1>не делает исключения.
template<class R, class T, class A1> unspecified-5 bind(R (T::*f) (), A1 a1)
template<class R, class T, class A1> unspecified-6 bind(R (T::*f) () const, A1 a1)
template<class R, class T, class A1> unspecified-6-1 bind(R T::*f, A1 a1)
template<class R, class F, class A1, class A2> unspecified-7 bind(F f, A1 a1, A2 a2)
  • Возвращение:Объект функции λ такой, что выражение λ<(v1,v2,...,vm)>эквивалентно<f(>μ<(a1,v1,v2,...,vm),>μ<(a2,v1,v2,...,vm))>, неявно преобразовано в<R>.
  • Броски:Ничего, кроме того, что создатели копий<F>,<A1>или<A2>не делают исключения.
template<class F, class A1, class A2> unspecified-7-1 bind(F f, A1 a1, A2 a2)
  • Эффекты:Эквивалентно<bind<typename F::result_type, F, A1, A2>(f,a1,a2)>.
  • Примечания:Осуществления допускаются для вывода о типе возврата<f>с помощью других средств в качестве расширения без использования элемента<result_type>.
template<class R, class B1, class B2, class A1, class A2> unspecified-8 bind(R (*f) (B1, B2), A1 a1, A2 a2)
  • 456Возврат:Объект функции λ такой, что выражение λ<(v1,v2,...,vm)>эквивалентно<f(>μ<(a1,v1,v2,...,vm),>μ<(a2,v1,v2,...,vm))>.
  • Броски:Ничего, кроме тех случаев, когда создатели копий<A1>или<A2>делают исключение.
template<class R, class T, class B1, class A1, class A2> unspecified-9 bind(R (T::*f) (B1), A1 a1, A2 a2)
  • Эффекты:Эквивалентно<bind<R>(><boost::mem_fn><(f),a1,a2)>.
template<class R, class T, class B1, class A1, class A2> unspecified-10 bind(R (T::*f) (B1) const, A1 a1, A2 a2)
  • Эффекты:Эквивалентно<bind<R>(><boost::mem_fn><(f),a1,a2)>.

Реализации могут обеспечивать дополнительные<bind>перегрузки для поддержки большего количества аргументов или различных вариаций указателей функций.

Эта реализация поддерживает функциональные объекты до девяти аргументов. Это деталь реализации, а не неотъемлемое ограничение дизайна.

Некоторые платформы допускают несколько типов (член) функций, которые отличаются по своей конвенции вызова (правила, по которым функция вызывается: как передаются аргументы, как обрабатывается возвращаемое значение и кто очищает стек - если таковой имеется).

Например, функции API Windows и функции членов интерфейса COM используют соглашение вызова, известное как<__stdcall>. Компоненты Borland VCL используют<__fastcall>. Функции набора инструментов Mac используют конвенцию вызова<pascal>.

Для использования<bind>с<__stdcall>функциями<#define>макрос<BOOST_BIND_ENABLE_STDCALL>перед включением<<boost/bind.hpp>>.

Для использования<bind>с функциями<__stdcall>,<#define>макрос<BOOST_MEM_FN_ENABLE_STDCALL>перед включением<<boost/bind.hpp>>.

Чтобы использовать<bind>с<__fastcall>функциями,<#define>макрос<BOOST_BIND_ENABLE_FASTCALL>перед включением<<boost/bind.hpp>>.

Для использования<bind>с функциями<__fastcall>,<#define>макрос<BOOST_MEM_FN_ENABLE_FASTCALL>перед включением<<boost/bind.hpp>>.

Для использования<bind>с<pascal>функциями<#define>макрос<BOOST_BIND_ENABLE_PASCAL>перед включением<<boost/bind.hpp>>.

Для использования<bind>с функциями<__cdecl>,<#define>макрос<BOOST_MEM_FN_ENABLE_CDECL>перед включением<<boost/bind.hpp>>.

Лучше всего определить эти макросы в параметрах проекта, через<-D>в командной строке или в качестве первой строки в блоке перевода (файл .cpp), где<bind>используется.Несоблюдение этого правила может привести к неясным ошибкам, когда заголовок включает<bind.hpp>до того, как был определен макрос.

[Примечание:это непортативное расширение. Он не является частью интерфейса.

[Примечание:Некоторые компиляторы обеспечивают только минимальную поддержку ключевого слова<__stdcall>.

Функциональные объекты, возвращаемые<bind>, поддерживают экспериментальный и пока незарегистрированный<visit_each>интерфейс перечисления.

См.bind_visitor.cppдля примера.

Предыдущие работы, которые повлияли на дизайн библиотеки:

Даг Грегор предположил, что механизм посетителя позволит<bind>взаимодействовать с библиотекой сигналов/слотов.

Джон Мэддок (John Maddock) устранил конфликт между<bindтипом библиотеки признаков.

Многочисленные улучшения были предложены в течение формального периода обзора Россом Смитом, Ричардом Кроссли, Йенсом Маурером, Эдом Бреем и другими. Менеджером по обзору был Дарин Адлер.

Точная семантика<bind>была доработана в дискуссиях с Jaakko Järvi.

Дэйв Абрахамс зафиксировал конфликт между<bindбиблиотекой итераторов.

Дэйв Абрахамс изменил<bind>и<mem_fn>для поддержки<void>возвратов на недостающие компиляторы.

Мак Мюрретт внес вклад в «паскальную» поддержку<BOOST_BIND_ENABLE_PASCAL>.

Альтернативный синтаксис<bind(type<R>(),f,...)>был вдохновлен дискуссией с Дэйвом Абрахамсом и Джоэлом де Гусманом.

Эта документация была портирована на Quickbook Agustín Bergé.

Последний пересмотр: 21 сентября 2016 года в 14:46:28 GMT


Статья Chapter 1. Boost.Bind раздела Chapter 1. Boost.Bind может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:14:01/0.023129940032959/1