Библиотека BOOST C++: заголовочный файл <boost/type_traits.hpp>

Содержание

Вступление

Первоначальная категоризация типов

Вторичная категоризация типов

Свойства типов

Отношения между типами

Преобразования между типами

Синтезирование типов

Свойства функций

Заголовочные файлы свойств типов

Пользовательские специализации

Примеры

Вступление

Содержимое (классы) заголовочного файла <boost/type_traits.hpp> объявляется в пространстве имен boost.

[an error occurred while processing this directive]

В файле <boost/type_traits.hpp> определены три вида свойств типов:

  1. свойства выбранного типа
  2. отношения между двумя типами
  3. преобразования от одного типа к другому

Если Вы ранее не работали с этой библиотекой, то предлагаем ознакомиться со статьей, где описываются основы и цели создания библиотеки.

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

Первичная категоризация типов

Нижеследующие шаблоны свойств типов позволяют определить, к какой категории типов принадлежит заданный тип. Для любого заданного типа только одно выражение получит значение true. Заметьте, что is_integral<T>::value и is_float<T>::value будут true только для встроенных типов; если есть необходимость проверки для пользовательских типов так же, как для встроенных, то следует использовать шаблон std::numeric_limits.

выражение

описание

ссылка

требования к компилятору

::boost::is_void<T>::value становится true только если T является cv-qualified void типом.

3.9.1p9

 
::boost::is_integral<T>::value становится true только если T является cv-qualified целым типом.

3.9.1p7

 
::boost::is_float<T>::value становится true только если T является cv-qualified типом с плавающей точкой

3.9.1p8

 
::boost::is_pointer<T>::value становится true только если T является cv-qualified указателем (включая указатели на функции, но исключая указатели на члены классов).

3.9.2p2

8.3.1

 
::boost::is_reference<T>::value становится true только если T является ссылкой.

3.9.2

8.3.2

если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон может давать неправильные результаты.
::boost::is_member_pointer<T>::value становится true только если T является a cv-qualified указателем на член класса (поле класса или метод).

3.9.2

8.3.3

 
::boost::is_array<T>::value становится true только если T является массивом.

3.9.2

8.3.4

если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон может давать неправильные результаты.
::boost::is_union<T>::value становится true только если T является типом union. В настоящее время требуется некоторая поддержка со стороны компилятора, иначе union'ы рассматриваются как классы.

3.9.2

9.5

Без определенной помощи со стороны компилятора (в настоящее время данная возможность не стандартизована), мы не можем отличить union от класса, в результате чего выражение никогда не получается true.
::boost::is_class<T>::value становится true только если T является классом или структурой.

3.9.2

9.2

Без определенной помощи со стороны компилятора (в настоящее время данная возможность не стандартизована), мы не можем отличать union от классов, в результате чего выражение дает неправильный ответ true для аргумента типа union.
::boost::is_enum<T>::value становится true только если T является перечислением (enum).

3.9.2

7.2

требуется правильно работающий шаблон is_convertible (это означает, что шаблон is_enum в настоящее время не работает в Borland C++ Builder 5, и в некоторых версиях компилятора Metrowerks).
::boost::is_function<T>::value становится true только если T является функциональным типом (но не ссылкой и не указателем на функцию).

3.9.2p1

8.3.5

если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон не компилируется для ссылочных типов.

 

Вторичная категоризация типов

Следующие категории типов создаются как комбинации одной или нескольких первичных категорий типов. Тип может принадлежать более чем одной из этих категорий, в дополнение к одной из первичных категорий.

Expression

Description

Reference

Compiler requirements

::boost::is_arithmetic<T>::value становится true только если T является cv-qualified арифметическим типом, то есть либо целочисленным, либо типом с плавающей точкой.

3.9.1p8

 
::boost::is_fundamental<T>::value становится true только если T является cv-qualified фундаментальным типом, то есть либо целым, либо с плавающей точкой, либо void.

3.9.1

 
::boost::is_object<T>::value становится true только если T является cv-qualified объектным типом, то есть не функцией, или типом void.

3.9p9

 
::boost::is_scalar<T>::value становится true только если T является cv-qualified скалярным типом, то есть арифметическим типом, перечислением, указателем или указателем на член класса.

3.9p10

Если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон не может быть использован с функциональными типами.
::boost::is_compound<T>::value становится true только если T является составным типом. (Любой тип, который не является фундаментальным, является составным).

3.9.2

::boost::is_member_function_pointer<T>::value становится true только если T является указателем на метод класса (и не указателем на поле данных в классе). Этот шаблон разбивает шаблон is_member_pointer на две подкатегории.

3.9.2

8.3.3

 

 

Свойства типов

Нижеописанные шаблоны идентифицируют свойства, которые имеет заданный тип.

выражение

описание

ссылка

требования к компилятору

::boost::alignment_of<T>::value

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

   
::boost::is_empty<T>::value

true если T является пустой структурой или классом. Если компилятор поддерживает метод оптимизации "пустые базовые классы нулевого размера", тогда шаблон is_empty может правильно определить, что T пустой. Используется шаблон is_class для определения, когда T является классом.

T должен быть полностью определен (complete type)

10p5

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

Не может быть использован с неопределенными полностью типами.

Не может работать с union'ами до тех пор, пока шаблон is_union сможет работать (см. его описание).

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

::boost::is_const<T>::value

true только если  T квалифицирован как const (top-level const-qualified).

3.9.3

 
::boost::is_volatile<T>::value

true только если  T квалифицирован как volatile.

3.9.3

 
::boost::is_polymorphic<T>::value

true только если  T является полиморфным типом.

T должен быть полностью определен (complete type)

10.3 Требуется знание ABI (?) компилятора, в действительности шаблон работоспособен на большинстве существующих компиляторов.
::boost::is_pod<T>::value true только если  T является cv-qualified POD, то есть простой структурой без методов, с возможными квалификаторами const и volatile.

T должен быть полностью определен (complete type).

3.9p10

9p4

Без некоторой помощи (в настоящее время эти возможности не стандартизованы) со стороны компилятора, шаблон is_pod не может определить, что T является POD; это безопасно, хотя может быть не оптимальным.

Если компилятор не поддерживает частичную специализацию шаблонов классов, то данный шаблон не может быть использован с функциональными типами.

::boost::has_trivial_constructor<T>::value true если T имеет простой деструктор, сгенерированный компилятором (trivial default constructor). 12.1p5

Без некоторой помощи (в настоящее время эти возможности не стандартизованы) со стороны компилятора, шаблон has_trivial_constructor не сможет определить, что заданный тип имеет пустой конструктор. Это всегда безопасно, хотя может быть неоптимальным.

Если компилятор не поддерживает частичную специализацию шаблонов классов, то данный шаблон не может быть использован с функциональными типами.

::boost::has_trivial_copy<T>::value true если T имеет простой сгенерированный компилятором конструктор копирования ( trivial copy constructor).

T должен быть полностью определен (complete type).

12.8p6

Без некоторой помощи (в настоящее время эти возможности не стандартизованы) со стороны компилятора, шаблон has_trivial_copy не сможет определить, что заданный тип имеет пустой конструктор копирования. Это всегда безопасно, хотя может быть неоптимальным.

Если компилятор не поддерживает частичную специализацию шаблонов классов, то данный шаблон не может быть использован с функциональными типами.

::boost::has_trivial_assign<T>::value true если T имеет простой сгенерированный компилятором оператор присваивания (trivial assignment operator).

T должен быть полностью определен (complete type).

12.8p11

Без некоторой помощи (в настоящее время эти возможности не стандартизованы) со стороны компилятора, шаблон has_trivial_assign не сможет определить, что заданный тип имеет пустой оператор присваивания. Это всегда безопасно, хотя может быть неоптимальным.

Если компилятор не поддерживает частичную специализацию шаблонов классов, то данный шаблон не может быть использован с функциональными типами.

::boost::has_trivial_destructor<T>::value true если T имеет простой, сгенерированный деструктор (trivial destructor).

T должен быть полностью определен (complete type).

12.4p3

Без некоторой помощи (в настоящее время эти возможности не стандартизованы) со стороны компилятора, шаблон has_trivial_destructor не сможет определить, что заданный тип имеет пустой оператор присваивания. Это всегда безопасно, хотя может быть неоптимальным.

Если компилятор не поддерживает частичную специализацию шаблонов классовв, то данный шаблон не может быть использован с функциональными типами.

::boost::is_stateless<T>::value true если T не имеет состояния, то есть T не выделяет память и его конструкторы и деструктор сгенерированы компилятором.

T должен быть полностью определен (complete type).

 

Без некоторой помощи (в настоящее время эти возможности не стандартизованы) со стороны компилятора, шаблон is_stateless не сможет определить, что заданный тип не имеет состояния. Это всегда безопасно, хотя может быть неоптимальным.

Выражение становится true только если становятся true все нижеуказанные:

::boost::has_trivial_constructor<T>::value,
::boost::has_trivial_copy<T>::value,
::boost::has_trivial_destructor<T>::value,
::boost::is_class<T>::value,
::boost::is_empty<T>::value

Если компилятор не поддерживает частичную специализацию шаблонов классов, то данный шаблон не может быть использован с функциональными типами.

::boost::has_nothrow_constructor<T>::value true если T имеет конструктор по умолчанию, не генерирующий исключения.

T должен быть полностью определен (complete type).

 

Без некоторой помощи (в настоящее время эти возможности не стандартизованы) со стороны компилятора, шаблон has_nothrow_constructor не сможет определить, что заданный тип имеет конструктор, не генерирующий исключения. Это всегда безопасно, хотя может быть неоптимальным.

Если компилятор не поддерживает частичную специализацию шаблонов классов, то данный шаблон не может быть использован с функциональными типами.

::boost::has_nothrow_copy<T>::value true если T имеет конструктор копирования, не генерирущий исключений.

T должен быть полностью определен (complete type).

 

Без некоторой помощи (в настоящее время эти возможности не стандартизованы) со стороны компилятора, шаблон has_nothrow_copy не сможет определить, что заданный тип имеет конструктор копирования, не генерирующий исключения. Это всегда безопасно, хотя может быть неоптимальным.

Если компилятор не поддерживает частичную специализацию шаблонов классов, то данный шаблон не может быть использован с функциональными типами.

::boost::has_nothrow_assign<T>::value true если T имеет оператор присваивания, не генерирующий исключений.

T должен быть полностью определен (complete type).

 

Без некоторой помощи (в настоящее время эти возможности не стандартизованы) со стороны компилятора, шаблон has_nothrow_assign не сможет определить, что заданный тип имеет оператор присваивания, не генерирующий исключения. Это всегда безопасно, хотя может быть неоптимальным.

Если компилятор не поддерживает частичную специализацию шаблонов классов, то данный шаблон не может быть использован с функциональными типами.

 

Отношения между типами

Следующая таблица содержит шаблоны, с помощью которых можно выяснить, есть ли какая-либо зависимость между двумя типами:

Expression

Description

Reference

Compiler requirements

::boost::is_same<T,U>::value

становится true, если T и U - один и тот же тип.

  если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон не может быть использован с  абстрактными, неполностью определенными или функциональными типами.
::boost::is_convertible<T,U>::value становится true, если воображаемый объект типа  T может быт преобразован в тип U.

Тип T не должен быть неполностью определенным типом.

Тип U не должен быть неполностью определенным, либо абстрактным типом, либо функциональным типом.

Подразумевается, что никакой тип не может быть преобразован в массив.

4

8.5

Обратите внимание, что данный шаблон работает неправильно с Borland C++ Builder 5 (и более ранними версиями) для преобразований через конструкторы, для с компилятором Metrowerks 7 (и более ранними версиями) во всех случаях.
::boost::is_base_and_derived<T,U>::value становится true, если T является базовым классом для типа U.

Будут обнаружены не-публичные базовые классы, и неоднозначные базовые классы.

Обратите внимание, что любой класс не рассматривается как собственный базовый класс. Аналогично, если T или U не являются классами, тогда результат будет в любом случае false.

Типы T и U не должны быть неполностью описанными.

10

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

Обратите внимание, что как is_convertible, так и is_base_and_derived могут привести к ошибке компиляции, если преобразование неоднозначно.:

struct A {};
struct B : A {};
struct C : A {};
struct D : B, C {};
bool const x = boost::is_base_and_derived<A,D>::value; // ошибка
bool const y = boost::is_convertible<D*,A*>::value; // ошибка

Преобразования между типами

Следующие шаблоны преобразовывают один тип в другой, основываясь на простом правиле: каждый шаблон имеет единственный член type, который является результатом применения преобразования к аргументу шаблона T:

Expression

Description

Reference

Compiler requirements

::boost::remove_const<T>::type Создает тип такой же как T, но убирает квалификатор const самого верхнего уровня. К примеру, "const int" становится"int", но "const int*" остается неизменным.  

если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон компилируется, но не работает, за исключением случаев, указанных в примечании ниже.

::boost::remove_volatile<T>::type Создает тип такой же как T, но убирает квалификатор volatile самого верхнего уровня. К примеру, "volatile int" становится "int".

3.9.333

если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон компилируется, но не работает, за исключением случаев, указанных в примечании ниже.

::boost::remove_cv<T>::type Создает тип такой же как T, но убирает квалификаторы const и volatile самого верхнего уровня. К примеру "const volatile int" становится "int". 3.9.3.3

если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон компилируется, но не работает, за исключением случаев, указанных в примечании ниже.

::boost::remove_reference<T>::type Если T является ссылкой, тогда удаляет ссылку, иначе тип T остается неизменным. К примеру, "int&" становится "int", но "int*" не изменится. 8.3.2

если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон компилируется, но не работает, за исключением случаев, указанных в примечании ниже.

::boost::remove_bounds<T>::type Если T является типом массива, тогда удаляет квалификатор верхнего уровня массива, в противном случае T не изменяется. К примеру,  "int[2][3]" становится "int[3]". 8.3.4

если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон компилируется, но не работает.

::boost::remove_pointer<T>::type Если T является указателем, тогда удаляет указатель верхнего уровня (top-level indirection) у T, иначе T остается неизменным. К примеру, "int*" становится "int", но "int&" не меняется. 8.3.1

если компилятор не поддерживает частичную специализацию шаблонов классов, тогда этот шаблон компилируется, но не работает, за исключением случаев, указанных в примечании ниже.

::boost::add_reference<T>::type Если T является ссылкой, тогда тип T не меняется, иначе преобразует T в ссылку. К примеру, "int&" не меняется, а  "double" становится "double&". 8.3.22  
::boost::add_pointer<T>::type Результатом работы является тип, который получается как remove_reference<T>::type*. К примеру, "int" и "int&" становятся "int*". 8.3.1

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

::boost::add_const<T>::type То же, что "T const" для всех T. 3.9.3  
::boost::add_volatile<T>::type То же, что "T volatile" для всех T. 3.9.3  
::boost::add_cv<T>::type То же, что "T const volatile" для всех T. 3.9.3  

Как видно по данной таблице, поддержка частичной специализации шаблонов классов необходима для правильной реализации шаблоном преобразования типов. С другой стороны, практика показывает, что многие шаблоны из данной категории очень полезны, и зачастую жизненно необходимы для реализации некоторых обобщенных библиотек (generic libraries). Отсутствие этих шаблонов часто является одним из главных ограничивающих факторов в портировании таких библиотек для компиляторов, которые все еще не поддерживают необходимые возможности языка C++. Поскольку некоторые из этих компиляторов будут использоваться еще какое-то время, а по крайней мере один из них широко распространен, было решено, что библиотека должна содержать решение проблемы, когда это возможно. Основной способ решения такой:

  1. Вручную создать полные специализации шаблонов для всех типов преобразований для всех фундаментальных типов, а также всех их указателей (* и **) с/без квалификаторами const и volatile
  2. Создать пользовательские макросы, которые будут определять такие явные специализации для любого пользовательского типа  T.

Первый пункт гарантирует успешную компиляцию такого фрагмента:

BOOST_STATIC_ASSERT((is_same<char, remove_reference<char&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char const, remove_reference<char const&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char volatile, remove_reference<char volatile&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char const volatile, remove_reference<char const volatile&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char*, remove_reference<char*&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char const*, remove_reference<char const*&>::type>::value));
....
BOOST_STATIC_ASSERT((is_same<char const volatile* const volatile* const volatile, remove_reference<char const volatile* const volatile* const volatile&>::type>::value));

и второй пункт обеспечивает для пользователей библиотеки механизм, с помощью которого вышеприведенный код будет работать не только для типов 'char', 'int' или других встроенных типов, но для любых пользовательских типов:

struct my {};
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(my)
BOOST_STATIC_ASSERT((is_same<my, remove_reference<my&>::type>::value));
BOOST_STATIC_ASSERT((is_same<my, remove_const<my const>::type>::value));
// etc.

Заметьте, что макрос BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION становится пустым для компиляторов, которые не поддерживают частичную специализацию.

Синтезирование типов

Следующие шаблоны синтезируют типы с желаемыми свойствами.

Выражение

Описание

Ссылка

Требования к комилятору

::boost::type_with_alignment<Align>::type пытается найти встроенный тип или POD, который имеет значение выравнивания такое же, как множитель заданного параметр а Align.    

Свойства функций

Шаблон класса ::boost::function_traits извлекает информацию о функциональном типе.

выражение

описание

ссылка

требования к компилятору

::boost::function_traits<F>::arity определяет арность функционального типа F.   без поддержки частичной специализации данный шаблон не компилируется для ссылочных типов.
::boost::function_traits<F>::result_type тип, возвращаемый функциональным типом F.   не компилируется без поддержки частичной специализации шаблонов классов.
::boost::function_traits<F>::argN_type тип Nго аргумента функции F, где 1<=N<=арность(F).   не компилируется без поддержки частичной специализации шаблонов классов.

Заголовочные файлы свойств типов

Библиотека свойств типов нормально подключается заголовочным файлом:

#include <boost/type_traits.hpp>

Однако в действительности библиотека разбита на ряд небольших файлов, так что иногда может быть удобнее включать один из этих файлов напрямую, чтобы получить только те шаблоны, которые нужны. Отдельные хидеры всегда имеют то же имя, что и соответствующий шаблон, и хранятся в каталоге boost/type_traits/.  Так что если, к примеру, некоторый код нуждается в шаблоне  is_class<>, тогда просто включайте:

<boost/type_traits/is_class.hpp>

Пользовательские специализации

В ряде случаев конечный пользователь может нуждаться в собственных специализациях для какого-либо из шаблонов свойств типов - обычно когда используемый компилятор требует, чтобы соответствующее свойство типа было реализовано полностью. Эти специализации должны наследовать от boost::mpl::true_ или boost::mpl::false_ соответственно:

[an error occurred while processing this directive]
#  include <boost/type_traits/is_pod.hpp>
# include <boost/type_traits/is_class.hpp>
# include <boost/type_traits/is_union.hpp>

struct my_pod{};
struct my_union
{
char c;
int i;
};

namespace boost
{
template<>
struct is_pod<my_pod>
: public mpl::true_{};
template<>
struct is_pod<my_union>
: public mpl::true_{};
template<>
struct is_union<my_union>
: public mpl::true_{};
template<>
struct is_class<my_union>
: public mpl::false_{};
}

Примеры

Есть четыре примера работы с шаблонами свойств типов:

Copy_example.cpp

Демонстрируется версия std::copy, которая использует функцию memcpy, когда это возможно, для выполнения копирования (то есть если тип - один из фундаментальных, либо POD, и т.д.);

//
// opt::copy
// same semantics as std::copy
// calls memcpy where appropiate.
//

namespace detail{

template<typename I1, typename I2>
I2 copy_imp(I1 first, I1 last, I2 out)
{
while(first != last)
{
*out = *first;
++out;
++first;
}
return out;
}

template <bool b>
struct copier
{
template<typename I1, typename I2>
static I2 do_copy(I1 first, I1 last, I2 out)
{ return copy_imp(first, last, out); }
};

template <>
struct copier<true>
{
template<typename I1, typename I2>
static I2* do_copy(I1* first, I1* last, I2* out)
{
memcpy(out, first, (last-first)*sizeof(I2));
return out+(last-first);
}
};


}

template<typename I1, typename I2>
inline I2 copy(I1 first, I1 last, I2 out)
{
typedef typename boost::remove_cv<typename std::iterator_traits<I1>::value_type>::type v1_t;
typedef typename boost::remove_cv<typename std::iterator_traits<I2>::value_type>::type v2_t;
return detail::copier<
::boost::type_traits::ice_and<
::boost::is_same<v1_t, v2_t>::value,
::boost::is_pointer<I1>::value,
::boost::is_pointer<I2>::value,
::boost::has_trivial_assign<v1_t>::value
>::value>::do_copy(first, last, out);
}

fill_example.cpp

Демонстрируется версия std::fill, которая использует функцию memset, когда это возможно, для оптимизации операции заполнения. Также используется шаблон call_traits для оптимизации передачи параметров, чтобы избежать проблем с синонимами (aliasing issues):

namespace opt{
///
// fill
// same as std::fill, uses memset where appropriate, along with call_traits
// to "optimise" parameter passing.
//
namespace detail{

template <typename I, typename T>
void do_fill_(I first, I last, typename boost::call_traits<T>::param_type val)
{
while(first != last)
{
*first = val;
++first;
}
}

template <bool opt>
struct filler
{
template <typename I, typename T>
struct rebind
{
static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val)
{ do_fill_<I,T>(first, last, val); }
};
};

template <>
struct filler<true>
{
template <typename I, typename T>
struct rebind
{
static void do_fill(I first, I last, T val)
{
std::memset(first, val, last-first);
}
};
};

}

template <class I, class T>
inline void fill(I first, I last, const T& val)
{
typedef detail::filler<
::boost::type_traits::ice_and<
::boost::is_pointer<I>::value,
::boost::is_arithmetic<T>::value,
(sizeof(T) == 1)
>::value> filler_t;
typedef typename filler_t:: template rebind<I,T> binder;
binder::do_fill(first, last, val);
}
}}; // namespace opt

iter_swap_example.cpp

Демонстрируется версия алгоритма std::iter_swap, который работает с прокси-итераторами (proxying iterators), а также с обычными итераторами; вызывает  std::swap для обычных итераторов, иначе выполняет медленный, но надежный обмен:

namespace opt{
///
// iter_swap:
// tests whether iterator is a proxying iterator or not, and
// uses optimal form accordingly:
//
namespace detail{

template <bool b>
struct swapper
{
template <typename I>
static void do_swap(I one, I two)
{
typedef typename std::iterator_traits<I>::value_type v_t;
v_t v = *one;
*one = *two;
*two = v;
}
};

template <>
struct swapper<true>
{
template <typename I>
static void do_swap(I one, I two)
{
using std::swap;
swap(*one, *two);
}
};

}

template <typename I1, typename I2>
inline void iter_swap(I1 one, I2 two)
{
typedef typename std::iterator_traits<I1>::reference r1_t;
typedef typename std::iterator_traits<I2>::reference r2_t;
detail::swapper<
::boost::type_traits::ice_and<
::boost::is_reference<r1_t>::value,
::boost::is_reference<r2_t>::value,
::boost::is_same<r1_t, r2_t>::value
>::value>::do_swap(one, two);
}

}; // namespace opt

Trivial_destructor_example.cpp

Этот алгоритм выполняет обратную по отношению к std::unitialized_copy работу; он получает указатель на блок инициализированной памяти и вызывает деструкторы для каждого из объектов в нем. Это может быть использовано при реализации контейнерных классов, которые самостоятельно управляют своей памятью:

namespace opt{
//
// algorithm destroy_array:
// The reverse of std::unitialized_copy, takes a block of
// initialized memory and calls destructors on all objects therein.
//

namespace detail{

template <bool>
struct array_destroyer
{
template <class T>
static void destroy_array(T* i, T* j){ do_destroy_array(i, j); }
};

template <>
struct array_destroyer<true>
{
template <class T>
static void destroy_array(T*, T*){}
};

template <class T>
void do_destroy_array(T* first, T* last)
{
while(first != last)
{
first->~T();
++first;
}
}

}; // namespace detail

template <class T>
inline void destroy_array(T* p1, T* p2)
{
detail::array_destroyer<boost::has_trivial_destructor<T>::value>::destroy_array(p1, p2);
}
} // namespace opt

Revised 22 April 2001

Documentation © Copyright John Maddock 2001. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.

The type traits library is based on contributions by Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, Jesse Jones, Mat Marcus, John Maddock and Jeremy Siek.

Mat Marcus and Jesse Jones have worked on, and published a paper describing the partial specialisation workarounds used in this library.

The is_convertible template is based on code originally devised by Andrei Alexandrescu, see "Generic<Programming>: Mappings between Types and Values".

Maintained by John Maddock, the latest version of this file can be found at www.boost.org, and the boost discussion list at boost@lists.boost.org (see http://www.boost.org/more/mailing_lists.htm#main).

последняя правка: 30.08.2005

библиотека BOOST C++ http://www.boost.org
перевод Elijah Koziev www.solarix.ru

  © Mental Computing 2010