Макро TTI<BOOST_TTI_HAS_TEMPLATE
>интроспектирует шаблон внутреннего класса класса. Макрос должен указать, по крайней мере, название шаблона класса для самоанализа.
Существует две общие формы интроспекции шаблона, которые могут быть использованы. Первый - найти шаблон класса с любым количеством параметров типа шаблона (параметры шаблона, начинающиеся с<class
>или<typename
>). В этой форме при вызове макроса необходимо указать только название шаблона класса. Мы будем называть эту форму макроса формой<template
typeparameters
>. Примером классного шаблона этой формы, который можно успешно интроспектировать, может быть:
template<class X,typename Y,class Z,typename T> class AClassTemplate { };
Во-вторых, найти шаблон класса с конкретными параметрами шаблона. В таком виде как название шаблона класса, так и параметры шаблона передаются на макрос.
Мы будем называть эту форму макроса формой<specific
parameters
>. Примером классного шаблона этой формы, который можно успешно интроспектировать, может быть:
template<class X, template<class> class Y, int Z> BClassTemplate { };
При использовании конкретной формы макроса есть две вещи, которые необходимо понимать при передаче параметров шаблона макросу. Во-первых, фактические имена пройденных параметров шаблона не имеют значения. Они могут быть полностью исключены или отличаться от названий в самом шаблоне вложенного класса. Во-вторых, использование «имя типа» или «класс», когда речь идет о параметре типа шаблона, полностью взаимозаменяемо, как и в самом шаблоне класса.
При использовании макроса BOOST_TTI_HAS_TEMPLATE мы различаем компиляторы, поддерживающие вариадные макросы или не поддерживающие вариадные макросы.
Программист всегда может сказать, поддерживает ли компилятор вариадные макросы, проверяя значение макроса. BOOST_PP_VARIADIC после включения необходимого файла заголовка<boost/tti/has_template.hpp
>для использования макроса BOOST_TTI_TEMPLATE. Значение 1 указывает, что компилятор поддерживает вариадные макросы, в то время как значение 0 указывает, что компилятор не поддерживает вариадные макросы.
Современные компиляторы C++, поддерживающие новейший стандарт C++11, обычно поддерживают вариадные макросы. Еще до последнего стандарта C++11 ряд компиляторов C++ уже поддерживали вариадные макросы. Если вы чувствуете, что ваш компилятор поддерживает вариадные макросы, а BOOST_PP_VARIADIC равен 0 даже после включения<boost/tti/has_template.hpp
>, вы можете предварительно определить BOOST_PP_VARIADIC до 1 до включения<boost/tti/has_template.hpp
>.
Мы начинаем с синтаксиса для компиляторов, не поддерживающих вариадные макросы, поскольку этот синтаксис также может использоваться компиляторами, которые поддерживают вариадные макросы. Форма для невариадных макросов всегда принимает два макропараметра. Первый макропараметр — это всегда название шаблона класса, который вы пытаетесь интроспектировать.
Второй макропараметр, при использовании<specific
parameters
>формы макроса, представляет собой параметры шаблона в виде типа массива данных препроцессорной библиотеки Boost. При использовании<template
typeparameters
>формы макроса вторым макропараметром является BOOST_PP_NIL. Если второй параметр не является типом данных препроцессорного библиотечного массива или BOOS_PP_NIL, вы получите ошибку компилятора, если ваш компилятор поддерживает только невариадные макросы.
Невариадная макроформа для интроспекции шаблонов классов выше с использованием формы<templatetype
parameters
>:
BOOST_TTI_TEMPLATE(AClassTemplate,BOOST_PP_NIL)
BOOST_TTI_TEMPLATE(BClassTemplate,BOOST_PP_NIL)
Вызов метафункции во втором случае всегда будет неудачным, поскольку BClassTemplate не имеет всех параметров типа шаблона.
Невариадная макроформа для интроспекции шаблонов классов выше с использованием формы<specificparameters
>:
BOOST_TTI_TEMPLATE(AClassTemplate,(4,(class,typename,class,typename)))
BOOST_TTI_TEMPLATE(BClassTemplate,(3,(class, template<class> class, int)))
Вы должны быть осторожны, используя невариадную форму<specific
parameters
>, чтобы указать правильное количество параметров массива. Иногда это может быть сложно, если у вас есть параметр шаблона шаблона или параметр шаблона без типа, который имеет скобки, окружающие часть спецификации типа. В последнем случае, когда скобки окружают запятую («,»), не учитывайте это как создание другого токена массива Boost PP. Два примера:
template<void (*FunctionPointer)(int,long)> class CClassTemplate { };
template<template<class,class> class T> class DClassTemplate { };
BOOST_TTI_TEMPLATE(CClassTemplate,(1,(void (*)(int,long))))
BOOST_TTI_TEMPLATE(DClassTemplate,(2,(template<class,class> class)))
В случае использования макроса для интроспекции CClassTemplate число параметров массива Boost PP равно 1, даже при наличии запятой, разделяющей токены в<void(*FunctionPointer)(int,long)
>. Это потому, что запятая находится в скобках.
В случае использования макроса для интроспективы DClassTemplate число параметров массива Boost PP равно 2, поскольку в<template<class,class>classT
>есть запятая, разделяющая токены.
Возможность использования вариадных макросов облегчает синтаксис для использования BOOST_TTI_TEMPLATE как в<template
typeparameters
>форме, так и в<specificparameters
>форме использования макроса. Это связано с тем, что вариадные макросы могут принимать переменное число параметров. При использовании вариадной макроформы первым макропараметром всегда является название шаблона класса, который вы пытаетесь интроспектировать. Вы указываете только дополнительные параметры при использовании<specific
parameters
>формы макроса, и в этом случае дополнительные параметры макроса являются конкретными параметрами шаблона.
Осмотр шаблона первого класса выше с использованием<template
typeparameters
>формы вариадного макроса будет:
BOOST_TTI_TEMPLATE(AClassTemplate)
Интроспектирование других шаблонов классов выше с использованием<specific
parameters
>формы вариадных макросов будет:
BOOST_TTI_TEMPLATE(BClassTemplate,class,template<class> class, int)
BOOST_TTI_TEMPLATE(CClassTemplate,void (*)(int,long))
BOOST_TTI_TEMPLATE(DClassTemplate,template<class,class> class)
Здесь у нас нет проблем с подсчетом количества токенов для массива Boost PP, и нам не нужно указывать BOOST_PP_NIL, если мы используем форму<templatetype
parameters
>. Также для конкретной формы параметров мы просто используем параметры шаблона в качестве оставшихся токенов вариадного макроса.
Используя любую форму макроса, будь то вариадный или невариадный синтаксис, макрос генерирует метафункцию, называемую «has_template_»name_of_inner_class_template.
Метафункция может быть вызвана путем передачи ее замкнутого типа для самоанализа.
Метафункция возвращает один тип, называемый «тип», который является импульсом::mpl::bool_. В качестве удобства метафункция возвращает значение этого типа непосредственно в виде константы времени компиляции, называемой «значением». Это истинно или ложно в зависимости от того, существует шаблон внутреннего класса или нет.