Распространяется под лицензией Boost Software License, версия 1.0. (См. сопроводительный файл LICENSE_1_0.txt или копию по адресу http://www.boost.org/LICENSE_1_0.txt)
boost::forward_adapter предоставляет шаблон многоразового адаптера для объектов функций. Он передает RValues как ссылки на const, оставляя LValues as-is.
structg// function object that only accept LValues{template<typenameT0,typenameT1,typenameT2>voidoperator()(T0&t0,T1&t1,T2&t2)const;typedefvoidresult_type;};// Adapted version also accepts RValues and forwards// them as references to const, LValues as-istypedefboost::forward_adapter<g>f;
Другой адаптер, boost::lighweight_forward_adapter позволяет пересылать с некоторой помощью от пользователя, принимающего и раскручивающего обертки ссылки (см. Boost.Ref) для опорных аргументов, в отличие от всех других аргументов.
Функции-мишени должны быть совместимы с Boost.ResultOf, как и адаптеры.
Предположим, что у нас есть функция f, которую мы можем назвать так:
f(123,a_variable);
Теперь мы хотим написать еще одну общую функцию g, которую можно назвать так же, и возвращаем некоторый объект, который вызывает f с теми же аргументами.
Возможно, мы хотим запустить f несколько раз. Или, может быть, мы хотим запустить его в другой поток. Может быть, мы просто хотим инкапсулировать выражение вызова на данный момент, а затем использовать его с другим кодом, который позволяет составлять более сложные выражения, чтобы разложить его на шаблоны C++ и заставить компилятор генерировать некоторые механизмы, которые в конечном итоге вызывают f во время выполнения (другими словами; применить технику, которую обычно называют шаблонами экспрессии).
Это происходит потому, что существует небольшая разница между переменной и выражением, которое оценивает ее значение: дано
inty;intconstz=0;
и
template<typenameT>voidfunc1(T&x);
мы можем позвонить
func1(y);// x is a reference to a non-const objectfunc1(z);// x is a reference to a const object
где
func1(1);// fails to compile.
Таким образом, мы можем безопасно хранить аргумент ссылки func1, и компилятор не позволяет нам хранить ссылку на объект с временным сроком службы.
Важно понимать, что непостоянство и связь объекта с эталонным параметром непостоянства являются двумя различными свойствами. Последнее является различием между LValues и RValues. Названия происходят от левой стороны и правой стороны выражений назначения, поэтому LValues обычно являются теми, которые вы можете назначить, и RValues временные результаты от выражения правой стороны.
y=1+2;// a is LValue, 1+2 is the expression producing the RValue,// 1+2 = a; // usually makes no sense. func1(y);// works, because y is an LValue// func1(1+2); // fails to compile, because we only got an RValue.
Если мы добавим по параметру квалификацию const, наша функция также принимает значения RV:
template<typenameT>voidfunc2(Tconst&x);// [...] function scope:func2(1);// x is a reference to a const temporary, object,func2(y);// x is a reference to a const object, while y is not const, andfunc2(z);// x is a reference to a const object, just like z.
Во всех случаях аргумент x в func2 является конст-квалифицированной LValue. Мы можем использовать перегрузку функций для идентификации неконстовых значений:
template<typenameT>voidfunc3(Tconst&x);// #1template<typenameT>voidfunc3(T&x);// #2// [...] function scope:func3(1);// x is a reference to a const, temporary object in #1,func3(y);// x is a reference to a non-const object in #2, andfunc3(z);// x is a reference to a const object in #1.
Обратите внимание, что все аргументы x в перегруженной функции func3 являются LValues. На самом деле, в C++98 нет способа перенести RValues в функцию as-is. Также обратите внимание, что мы не можем отличить то, что раньше было квалифицированной LValue от RValue.
Это максимально близко к общей функции пересылки g, как описано выше с помощью C++. 98. См. The Forwarding Problem для очень подробного обсуждения, включая решения, требующие языковых изменений.
Теперь, для фактической реализации, нам нужны перегрузки 2N для N параметров (каждый с и без квалификатора const) для каждого числа аргументов (то есть 2^(Nmax+1) - 2^Nmin). Правильно, это означает, что сложность компиляции составляет O(2^N), но коэффициент низкий, поэтому он хорошо работает для разумного числа (<10) аргументов.
Шаблон адаптера функциональных объектов, экземпляры которого можно назвать аргументами LValue и RValue. Аргументы RValue пересылаются в виде LValues типа «ссылка-конст».
Арити может быть дано в качестве второго, числового нетипового шаблонного аргумента, чтобы ограничить пересылку к конкретной аритмии. Если присутствует третий аргумент шаблона, не относящийся к типу, второй и третий аргумент шаблона рассматриваются как минимум и максимум. Определение аритмии может быть полезно для улучшения читаемости диагностических сообщений и компиляции производительности времени.
Boost.ResultOf может использоваться для определения типов результатов конкретных выражений вызовов.
Время предварительной обработки: O(2^N), где N - предел аритмии. Время компиляции: O(2^N), где N зависит от аритмии. Время выполнения: O(0), если компилятор входит, O(1) в противном случае.
Шаблон адаптера функциональных объектов, экземпляры которого можно назвать аргументами LValue и RValue. Все аргументы пересылаются в виде LValues типа «ссылка-конст», за исключением оберток, которые не обернуты и могут давать неконстовые LValues.
Арити может быть дано в качестве второго, числового нетипового шаблонного аргумента, чтобы ограничить пересылку к конкретной аритмии. Если присутствует третий аргумент шаблона, не относящийся к типу, второй и третий аргумент шаблона рассматриваются как минимум и максимум. Определение аритмии может быть полезно для улучшения читаемости диагностических сообщений и компиляции производительности времени.
Boost.ResultOf может использоваться для определения типов результатов конкретных выражений вызовов.
Время предварительной обработки: O(N), где N - предел аритмии. Время компиляции: O(N), где N - эффективная частота вызова. Время выполнения: O(0), если компилятор входит, O(1) в противном случае.
Поскольку эти утилиты учитываются из функционального модуля Boost.Fusion, я хочу поблагодарить Дэна Марсдена и Джоэла де Гусмана за то, что они позволили мне участвовать в разработке этой замечательной библиотеки.
Кроме того, я хочу отдать должное авторам приведенных ниже ссылок за их глубокое исследование проблемы и решения, реализованного здесь.
И последнее, но не менее важное: я хочу поблагодарить Весу Карновена и Пола Менсонидеса за библиотеку Boost Preprocessor. Без него у меня был бы внешний генератор кода для этого.
Boost.Ref, Яакко Джарви, Питер Димов, Дуглас Грегор, Дэвид Абрахамс, 1999-2002
Последние изменения: 01 ноября 2008 г. в 19:58:50 мск
Статья Chapter 1. Boost.Functional/Forward 1.0 раздела Chapter 1. Boost.Functional/Forward 1.0 может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.