Макро<BOOST_TTI_HAS_TYPE
>TTI интроспектирует вложенный тип класса.
Макро BOOST_TTI_HAS_TYPE берет один параметр, который является именем внутреннего типа, существование которого программист хочет проверить. Макро генерирует метафункцию, называемую «has_type_»name_of_inner_type.
Основной целью генерируемой метафункции является проверка существования по названию внутреннего типа. Метафункция также может быть использована для вызова выражения лямбда MPL, которое передается внутренним типом. Одним из наиболее распространенных применений добавленной функциональности является проверка того, является ли внутренний тип типом для другого типа.
Метафункция вызывается путем передачи ей замкнутого типа для самоанализа. Второй тип может быть передан метафункции, выражение лямбда MPL принимает внутренний тип и возвращает булеву константу.
Метафункция возвращает один тип, называемый «тип», который является импульсом::mpl::bool_. В качестве удобства метафункция возвращает значение этого типа непосредственно в виде константы времени компиляции, называемой «значением». Это значение истинно или ложно в зависимости от того, существует внутренний тип или нет.
Если второй необязательный тип принят, этот тип должен быть лямбда-выражением MPL, и выражение будет вызываться только в том случае, если существует внутренний тип. В этом случае метафункция возвращается истинной или ложной в зависимости от того, является ли выражение лямбда истинным или ложным. Если внутренний тип не существует, выражение лямбда, даже если оно указано, никогда не вызывается, и метафункция возвращается ложной.
Вы генерируете метафункцию, вызывая макрос с именем внутреннего типа:
BOOST_TTI_HAS_TYPE(AType)
генерирует метафункцию под названием «has_type_AType» в текущем объеме.
Вы вызываете метафункцию, инстанцируя шаблон с закрытым типом для самоанализа и, необязательно, выражением лямбда MPL. Возвратное значение, называемое «значением», представляет собой константу компиляции времени.
has_type_AType<Enclosing_Type>::value
has_type_AType<Enclosing_Type,ALambdaExpression>::value
Сначала мы генерируем метафункции для различных внутренних имен типов:
#include <boost/tti/has_type.hpp>
BOOST_TTI_HAS_TYPE(MyTypeDef)
BOOST_TTI_HAS_TYPE(AType)
BOOST_TTI_HAS_TYPE(ATypeDef)
BOOST_TTI_HAS_TYPE(MyType)
Давайте создадим некоторые пользовательские типы, которые мы хотим интроспектировать.
struct Top
{
typedef int MyTypeDef;
struct AType { };
};
struct Top2
{
typedef long ATypeDef;
struct MyType { };
};
Наконец, мы прибегаем к нашей метафункции и возвращаем нашу ценность.
has_type_MyTypeDef<Top>::value;
has_type_MyTypeDef<Top2>::value;
has_type_AType<Top>::value;
has_type_AType<Top2>::value;
has_type_ATypeDef<Top>::value;
has_type_ATypeDef<Top2>::value;
has_type_MyType<Top>::value;
has_type_MyType<Top2>::value;
Мы можем дополнительно вызвать нашу метафункцию со вторым типом, который является выражением лямбда MPL.
Выражение лямбда MPL, чрезвычайно полезная техника в метапрограммировании шаблонов, позволяет нам передавать метафункцию другим метафункциям. Метафункция, которую мы проходим, может быть в виде экспрессии заполнителя или класса метафункций. В нашем случае метафункция, переданная нашей метафункции имеет_type_'name_of_inner_type' в качестве лямбда-выражения, должна возвращать булеву постоянную экспрессию.
Сначала мы проиллюстрируем использование выражения лямбда в виде выражения заполнителя, передаваемого в качестве второго параметра шаблона для нашей метафункции _type_'name_of_inner_type. Популярным и простым выражением, которое мы можем использовать, является «boost::is_same<_1, Some». Type>, чтобы проверить, является ли найденный внутренний тип конкретным типом. Это особенно полезно, когда внутренний тип является типизированным для другого типа.
Во-первых, мы включаем еще несколько файлов заголовков и декларацию об использовании для удобства.
#include <boost/mpl/placeholders.hpp
#include <boost/type_traits/is_same.hpp
using namespace boost::mpl::placeholders;
Далее мы ссылаемся на нашу метафункцию:
has_type_MyTypeDef<Top,boost::is_same<_1,int> >::value;
has_type_MyTypeDef<Top,boost::is_same<_1,long> >::value;
has_type_ATypeDef<Top2,boost::is_same<_1,int> >::value;
has_type_ATypeDef<Top2,boost::is_same<_1,long> >::value;
Далее мы проиллюстрируем использование лямбда-выражения в виде класса метафункций, передаваемого в качестве второго параметра шаблона нашей метафункции _type_'name_of_inner_type.
Класс метафункций — это тип, который имеет вложенный шаблон класса, называемый «применить». Для нашего примера класса метафункций мы проверим, является ли внутренний тип встроенным целым типом. Для начала запишем класс метафункций:
#include <boost/type_traits/is_integral.hpp>
class OurMetafunctionClass
{
template<class T> struct apply :
boost::is_integral<T>
{
};
};
Теперь мы можем воспользоваться нашей метафункцией:
has_type_MyTypeDef<Top,OurMetafunctionClass>::value;
has_type_AType<Top,OurMetafunctionClass>::value;
has_type_ATypeDef<Top2,OurMetafunctionClass>::value;
has_type_MyType<Top2,OurMetafunctionClass>::value;
Макрокодирует только название внутреннего типа, для которого мы ищем, и тот факт, что мы ищем внутренний тип внутри закрытого типа.
Из-за этого, как только мы создаем нашу метафункцию для интроспекции внутреннего типа по имени, мы можем повторно использовать метафункцию для интроспекции любого замкнутого типа, имеющего любой внутренний тип, для этого имени.
Кроме того, поскольку мы закодировали только название внутреннего типа, для которого мы интроспектируем, мы можем не только интроспектировать этот внутренний тип по имени, но и добавлять различные выражения лямбда, чтобы проверить этот внутренний тип на предмет того, что мы хотим узнать о нем, используя ту же метафункцию.