Некоторые типы данных, такие как C++ Передовые и двунаправленные итераторы Стандартной библиотеки не обеспечивают сложение и вычитание через оператор +() или оператор-(). Это означает, что для немодифицирующего вычисления следующего или предыдущего значения требуется временное, хотя оператор++() Предоставляется оператор (-). Это также означает, что написание кода<itr+1>внутри шаблона ограничивает категорию итератора итераторами случайного доступа.
Следующие () и предыдущие () функции обеспечивают простой способ обойти эти проблемы:
template <class T>
T next(T x) { return ++x; }
template <class T, class Distance>
T next(T x, Distance n)
{
std::advance(x, n);
return x;
}
template <class T>
T prior(T x) { return --x; }
template <class T, class Distance>
T prior(T x, Distance n)
{
std::advance(x, -n);
return x;
}
Использование простое:
const std::list<T>::iterator p = get_some_iterator();
const std::list<T>::iterator prev = boost::prior(p);
const std::list<T>::iterator next = boost::next(prev, 2);
Расстояние от заданного итератора должно подаваться как абсолютное значение. Например, итератор четыре итератора до данного итератора<p>может быть получен<prior(p, 4)>.
Дэйв Абрахамс. Двухаргументные версии Дэниела Уокера.
Шаблон класса<result_of>помогает определить тип выражения вызова. Например, при данном lvalue<f>типа<F>и lvalues<t1>,<t2>, ...,<tN>типов<T1>,<T2>, ...,<TN>, соответственно, тип<result_of<F(T1, T2, ...,
TN)>::type>определяет тип результата выражения<f(t1, t2,
...,tN)>. Эта реализация позволяет типу<F>быть указателем функции, эталоном функции, указателем функции члена или типом класса. По умолчаниюNможет быть любым значением между 0 и 16. Чтобы изменить верхний предел, определите макрос<BOOST_RESULT_OF_NUM_ARGS>до максимального значения дляN. Шаблон класса<result_of>находится в заголовке<<boost/utility/result_of.hpp>>.
Если поддержка компилятора<decltype>является адекватной,<result_of>автоматически использует его для вывода типа выражения вызова, в этом случае<result_of<F(T1, T2, ...,
TN)>::type>называет тип<decltype(boost::declval<F>()(boost::declval<T1>(),
boost::declval<T2>(), ...,
boost::declval<TN>()))>, как в следующем примере.
struct functor {
template<class T>
T operator()(T x)
{
return x;
}
};
typedef boost::result_of<
functor(int)
>::type type; // type is int
Вы можете проверить, использует ли<result_of><decltype>, проверив, определен ли макрос<BOOST_RESULT_OF_USE_DECLTYPE>после включения<result_of.hpp>. Вы также можете заставить<result_of>использовать<decltype>, определив<BOOST_RESULT_OF_USE_DECLTYPE>до включения<result_of.hpp>.
Если<decltype>не используется, то автоматическое выведение типа результата объектов функции невозможно. Вместо этого<result_of>используется следующий протокол, позволяющий программисту указать тип. Когда<F>является типом класса с типом члена<result_type>,<result_of<F(T1, T2, ...,
TN)>::type>является<F::result_type>. Когда<F>не содержит<result_type>,<result_of<F(T1, T2, ...,
TN)>::type>—<F::result<F(T1,
T2, ..., TN)>::type>, когда<N> 0>или<void>, когда<N= 0>. Обратите внимание, что программист несет ответственность за то, чтобы объекты функций точно рекламировали свой тип результата через этот протокол, как в следующем примере.
struct functor {
template<class> struct result;
template<class F, class T>
struct result<F(T)> {
typedef T type;
};
template<class T>
T operator()(T x)
{
return x;
}
};
typedef boost::result_of<
functor(int)
>::type type; // type is int
Поскольку<decltype>является новой языковой функцией, недавно стандартизированной в C++11, если вы пишете объект функции для использования с<result_of>, для максимальной переносимости вы можете рассмотреть возможность следования вышеупомянутому протоколу, даже если ваш компилятор имеет надлежащую поддержку<decltype>. Если вы хотите продолжать использовать протокол на компиляторах, поддерживающих<decltype>, есть два варианта: Вы можете использовать<boost::tr1_result_of>, который также определен в<<boost/utility/result_of.hpp>>. В качестве альтернативы можно определить макрос<BOOST_RESULT_OF_USE_TR1>, который заставляет<result_of>использовать протокол, описанный выше, вместо<decltype>. Если вы решили следовать протоколу, позаботьтесь о том, чтобы члены<result_type>и<result<>>точно представляли тип возврата<operator()>при наличии выражения вызова.
Кроме того,<boost::result_of>обеспечивает третий режим работы, который некоторые пользователи могут счесть удобным. Когда<BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK>определено,<boost::result_of>ведет себя следующим образом. Если объект функции имеет тип члена<result_type>или шаблон члена<result<>>, то<boost::result_of>будет использовать протокол TR1. В противном случае<boost::result_of>будет использовать<decltype>. Использование TR1 с запасным вариантом<declytpe>может обойти некоторые проблемы за счет переносимости. Например:
Недопустимо, что это не так.< [17] >,< [17] >,< [17] >,< [17] >,< [18] >,< [18] >,< [17] >,< [17] >,< [17] >,< [17] >,< [17] >,< [17] >,< [17] >,< [17] >,< [18] >,< [18] >,< [18] >. Поддержку имеют C++11 (см.N3276) и выравнивание.
Недостаток: Если же TR1 рекламируется как TR1, то на самом деле, как< [23] >, то на TR1 как< [23] >как< [23] >, как< [23] >, так и на C++11. Если это не так, то мы имеем дело с устаревшим протоколом TR1. См. документацию,< [25] >и TR1.
Эта реализация<result_of>требует частичной специализации шаблона классов, возможности правильного анализа типов функций и поддержки SFINAE. Если<result_of>не поддерживается вашим компилятором, в том числе заголовок<boost/utility/result_of.hpp>будет определять макрос<BOOST_NO_RESULT_OF>.Недостаточный компилятор: Если ваш код требуетboost::result_ofдля работы с неполными типами возврата, но реализация вашего компилятораdecltypeне поддерживает неполные типы возврата, то вы можете использовать протокол TR1 в качестве обходного пути. Поддержка неполных типов возврата была добавлена позднее в процессе стандартизации C++11 (см.N3276) и не реализована некоторыми компиляторами.
Недостаточный код наследия: Если ваш существующий объект функции TR1 рекламирует другой тип, чем фактический тип результата, выведенныйdecltype, то использование TR1 с запасным вариантомdecltypeпозволит вам работать как с существующими объектами функции TR1, так и с новым объектом функции C++11. Эта ситуация может возникнуть, если ваши объекты устаревших функций неправильно использовали протокол TR1. См. документацию по известнымразличияммеждуboost::result_ofи TR1.
This implementation of result_of
requires class template partial specialization, the
ability to parse function types properly, and support
for SFINAE. If result_of is not supported
by your compiler, including the header
boost/utility/result_of.hpp will
define the macro BOOST_NO_RESULT_OF.[ORIG_END] -->
Для получения дополнительной информации о<result_of>, см. C++ Library Technical Report,N1836, или, для мотивации и обоснования дизайна, предложение<result_of>.
Ниже приведены общие рекомендации о том, когда и как использовать<boost::result_of>.
Если вы ориентируетесь на C++11 и не беспокоитесь о переносимости на несоответствующие компиляторы или предыдущие версии стандарта, то используйтеstd::result_of. Еслиstd::result_ofудовлетворяет ваши потребности, то нет причин прекращать его использование.
Если вы нацеливаетесь на C++11, но в будущем можете портировать свой код на устаревшие компиляторы, используйтеboost::result_ofсdecltype. Когдаdecltypeиспользуетсяboost::result_ofиstd::result_ofобычно взаимозаменяемы. См. документацию по известнымразличияммежду boost::result_of и C++11 result_of.
Если требуется переносимость компилятора, используйтеboost::result_ofс протоколом TR1.
Независимо от того, как вы настраиваете<boost::result_of>, важно иметь в виду, что тип возврата функции может изменяться в зависимости от ее аргументов, а также тип возврата функции члена может изменяться в зависимости от cv-квалификации объекта.<boost::result_of>должны быть пройдены соответствующие cv-квалифицированные типы, чтобы вывести соответствующий тип возврата. Например:
<
struct functor {
int& operator()(int);
int const& operator()(int) const;
float& operator()(float&);
float const& operator()(float const&);
};
typedef boost::result_of<
functor(int)
>::type type1; // type1 is int &
typedef boost::result_of<
const functor(int)
>::type type2; // type2 is int const &
typedef boost::result_of<
functor(float&)
>::type type3; // type3 is float &
typedef boost::result_of<
functor(float const&)
>::type type4; // type4 is float const &
На совместимых компиляторах C++11<boost::result_of>можно использовать<decltype>для вывода типа любого выражения вызова, включая вызовы для функционирования объектов. Однако на компиляторах до C++11 или на компиляторах без адекватной поддержки деклотипа необходимы дополнительные строительные леса из функциональных объектов, как описано выше. Ниже приведены рекомендации по использованию протокола TR1.
Когда тип возврата не зависит от типов аргументов или от квалификации объекта функции, просто определитеresult_type. Нет необходимости использовать шаблонresult, если тип возврата не изменяется.
Используйте протокол заданного типа при определении функции прототипов. Это может помочь гарантировать, что фактический тип возврата не выйдет из синхронизации со спецификацией протокола. Например:
struct functor {
typedef int result_type;
result_type operator()(int);
};
Всегда уточняйте специализациюresultвблизи соответствующейoperator()перегрузки. Это может облегчить синхронизацию специализаций с перегрузками. Например:
Используйте преобразования типов, чтобы упростить специализацию шаблонаresult. Для этого используется. TypeTraitsдля специализации шаблонаresultдля одногоoperator(), который может быть вызван как на объект функции const, так и на объект функции non-const с аргументом lvalue или rvalue.
When using decltype, boost::result_of
ignores the TR1 protocol and instead deduces the
return type of function objects directly
via decltype. In most situations, users
will not notice a difference, so long as they use the
protocol correctly. The following are situations in
which the type deduced
by boost::result_of is known to differ depending on
whether decltype or the TR1 protocol is
used.
TR1 protocol misusage
При использовании протокола TR1<boost::result_of>не может определить, является ли фактический тип вызова функциональному объекту тем же, что и тип, указанный протоколом, что допускает возможность непреднамеренного несоответствия между указанным типом и фактическим типом. При использовании<decltype>эти тонкие ошибки могут привести к ошибкам компиляции. Например:
Обратите внимание, что пользователь может заставить<boost::result_of>использовать протокол TR1 даже на платформах, поддерживающих<decltype>, определив<BOOST_RESULT_OF_USE_TR1>.
Nullary function objects
При использовании протокола TR1<boost::result_of>не всегда можно вывести тип вызовов к объектам нулевой функции, в этом случае тип по умолчанию недействителен. При использовании<decltype>,<boost::result_of>всегда дает фактический тип выражения вызова. Например:
struct functor {
template<class> struct result {
typedef int type;
};
int operator()();
};
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same<boost::result_of<functor()>::type, int>::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same<boost::result_of<functor()>::type, void>::value
));
#endif
Обратите внимание, что есть некоторые обходные пути для проблемы нулевой функции. До тех пор, пока тип возврата не изменяется,<result_type>всегда можно использовать для указания типа возврата независимо от аритмии. Если тип возврата изменяется, то пользователь может специализироваться<boost::result_of>для неполных вызовов.
Non-class prvalues and cv-qualification
При использовании протокола TR1<boost::result_of>будет сообщать о cv-квалифицированном типе, указанном в<result_type>или шаблоне<result>, независимо от фактической cv-квалификации выражения вызова. При использовании<decltype>,<boost::result_of>будет сообщать о фактическом типе выражения вызова, который не квалифицирован, когда выражение является неклассовым значением. Например:
struct functor {
template<class> struct result;
template<class F, class T> struct result<F(const T)> {
typedef const T type;
};
const short operator()(const short);
int const & operator()(int const &);
};
// Non-prvalue call expressions work the same with or without decltype.
BOOST_STATIC_ASSERT((
boost::is_same<
boost::result_of<functor(int const &)>::type,
int const &
::value
));
// Non-class prvalue call expressions are not actually cv-qualified,
// but only the decltype-based result_of reports this accurately.
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same<
boost::result_of<functor(const short)>::type,
short
::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same<
boost::result_of<functor(const short)>::type,
const short
::value
));
#endif
При использовании<decltype>,<boost::result_of>реализуется большая часть C++11 результата_ спецификации. Одним из известных исключений является то, что<boost::result_of>не выполняет требования, касающиеся указателей на данные членов.
Создан Дугом Грегором. Вклады Даниэля Уокера, Эрика Ниблера, Мишеля Морина и других
Макро<BOOST_BINARY>используется для представления двоичных букв. Он принимает в качестве аргумента двоичное число, расположенное как произвольное количество 1s и 0s в группах длины от 1 до 8, с группами, разделенными пространствами. Тип получаемого литерала определяется теми же правилами, что и шести- и восьмибуквенные буквы2.13.1p1. Благодаря реализации этот макрос расширяется непосредственно до октального литерала во время предварительной обработки, поэтому во время выполнения нет накладных расходов, и результат можно использовать в любом месте, где будет октальный литерал.
Для непосредственной поддержки двоичных букв суффиксами также предусмотрены дополнительные макросы формы BOOST_BINARY_XXX, где XXX является стандартным целым суффиксом во всех заглавных буквах. Кроме того, суффиксы LL и ULL могут использоваться для представления длиннодлинных и неподписанных длиннодлинных типов в компиляторах, которые предоставляют их в качестве расширения.
Семейство макросов BOOST_BINARY находится в заголовке, который автоматически включается в.
Вклад Мэтта Калабрезе.
Example
void foo( int );
void foo( unsigned long );
void bar()
{
int value1 = BOOST_BINARY( 100 111000 01 1 110 );
unsigned long value2 = BOOST_BINARY_UL( 100 001 ); // unsigned long
long long value3 = BOOST_BINARY_LL( 11 000 ); // long long if supported
assert( BOOST_BINARY( 10010 )
& BOOST_BINARY( 11000 )
== BOOST_BINARY( 10000 )
);
foo( BOOST_BINARY( 1010 ) ); // calls the first foo
foo( BOOST_BINARY_LU( 1010 ) ); // calls the second foo
}
Revised 04 September, 2008
Авторское право Beman Dawes 1999-2003.
Распространяется в соответствии с Лицензией на программное обеспечение Boost, версия 1.0. См.www.boost.org/LICENSE_1_0.txt
Статья Header boost/utility.hpp Documentation раздела может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.