![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Nested TypesBoost , Chapter 1. The Type Traits Introspection Library , Chapter 1. The Type Traits Introspection Library
|
Внутренний элемент |
Макро |
шаблон |
Специфический файл заголовка |
---|---|---|---|
Тип |
класс T = прилагающийся класс типа U = (необязательно) тип маркера возвращается = тип 'name', если он существует, иначе тип маркера, как тип typedef'. Вызванная метафункция также содержит тип маркера в виде типдефа «boost_tti_marker_type». Это делается для удобства, чтобы не пришлось запоминать тип маркера. |
Тип маркера является чисто факультативным. Если не указан тип внутренней библиотеки TTI, которая не имеет функциональности, используется. Если у конечного пользователя нет конкретной причины предоставить свой собственный тип маркера, он должен позволить библиотеке TTI использовать свой собственный тип внутреннего маркера.
Простой пример такой функциональности:
#include <boost/tti/member_type.hpp> BOOST_TTI_MEMBER_TYPE(ANamedType) typedef typename member_type_ANamedType<EnclosingType>::type AType;
Если тип «ANamedType» является вложенным типом «EnclosingType», то AType является тем же типом, что и «ANamedType», в противном случае AType является маркерным типом внутри библиотеки TTI.
Теперь, когда мы объяснили синтаксис BOOST_TTI_MEMBER_TYPE Теперь мы можем ответить на вопрос, почему эта функциональность для создания «типа» существует при поиске вложенного типа замкнутого типа.
Метафункции, генерируемые макросами TTI, работают с различными типами, будь то при определении типа ограждающего элемента или при определении типа некоторого внутреннего элемента, который также может включать типы в подписи этого элемента, такие как параметр или тип возврата функции. Нотацией C++ для вложенного типа, учитывая прилагаемый тип «T» и внутренний тип «InnerType», является «T:: InnerType». Если в «T» не существует замкнутого типа «T», или внутри «T» не существует внутреннего типа «InnerType», выражение «T::InnerType» даст ошибку компилятора, если мы попытаемся использовать его в нашем шаблонном воплощении одной из макрометафункций TTI.
Это проблема, если мы хотим иметь возможность интроспектировать существование внутренних элементов в замкнутый тип без ошибок компилятора. Конечно, если мы точно знаем, какие типы у нас есть, и что вложенный тип существует, и эти объявления находятся в пределах нашей области, мы всегда можем использовать выражение, такое как T:: InnerType, без ошибки компилятора. Но это часто не так при программировании шаблонов, поскольку тип, передаваемый нам во время компиляции в шаблоне класса или функции, выбирается во время инстанциации и создается пользователем шаблона.
Одним из решений этой проблемы является сама библиотека. Учитывая замкнутый тип «Т», который, как мы знаем, должен существовать, либо потому, что это тип верхнего уровня, о котором мы знаем, либо он передается нам в каком-то шаблоне как «класс Т» или «типовое имя Т», и учитывая внутренний тип под названием «внутренний тип», существование которого мы хотели бы установить, мы можем использовать.BOOST_TTI_HAS_TYPEВнутренний тип
макрос и связанный с нимимеет метафункцию_type_InnerType
для определения наличия вложенного типа «Внутренний тип». Это решение является абсолютно верным, и в сочетании с метафункциями выбора Boost MPL мы можем сделать выбор времени компиляции для создания правильного кода шаблона.
Однако это не так хорошо синтаксически масштабируется, если нам нужно сверлить дальше от ограждающего типа верхнего уровня до глубоко вложенного типа или даже искать внутренние элементы какого-то глубоко вложенного типа. Мы собираемся произвести многоповышения::mpl::, если
и/илиповышения::mpl::eval_if
Заявления выбора типа, чтобы добраться до некоторого конечного состояния, когда мы знаем, что можем генерировать код времени компиляции, который мы хотим.
Решение, данное BOOST_TTI_MEMBER_TYPE, заключается в том, что мы можем создать тип в качестве возврата от нашей метафункции, который является тем же типом, что и вложенный тип, если он существует, или какой-либо другой тип маркера, если он не существует, а затем работать с этим возвращенным типом, не создавая ошибки компилятора. Если бы нам пришлось использовать синтаксис «T::InnerType», чтобы указать наш тип, где «T» представляет собой вложенный тип и «InnerType» наш вложенный тип, и не было бы вложенного типа «InnerType» в вложенном типе «T», компилятор немедленно дал бы нам ошибку.
Используя BOOST_TTI_MEMBER_TYPE У нас есть тип, с которым можно работать, даже если такого типа на самом деле не существует. Естественно, если тип не существует, то тип, с которым мы должны работать, будучи маркерным типом, как правило, не будет выполнять другие функции, которые мы хотим от него. Это хорошо и, как правило, дает правильные результаты при дальнейшем использовании этого типа при программировании метафункций. Иногда тип маркера, полученный TTI, когда наш вложенный тип не существует, не достаточен для дальнейшего программирования метафункций. В этом редком случае конечный пользователь может создать свой собственный тип маркера, который будет использоваться, если вложенный тип не существует. В любом случае, существует ли вложенный тип, используется ли тип маркера по умолчанию TTI или используется тип маркера конечного пользователя, метапрограммирование шаблона может продолжаться без проблемы компиляции. Кроме того, эта шкала лучше, чем постоянная проверка наличия вложенного типа через BOOST_TTI_HAS_TYPE в сложном шаблонном метапрограммном коде.
Как только мы используем BOOST_TTI_MEMBER_TYPE для создания вложенного типа, если он существует, мы обычно используем этот тип в дальнейшем программировании метафункций. Иногда, учитывая тип, который мы генерируем, мы захотим спросить, действительно ли тип является нашим вложенным типом или типом маркера. По сути, мы спрашиваем, является ли генерируемый тип маркерным или нет. Если это тип маркера, то генерируемый тип не является вложенным типом, на который мы надеялись. Если это не тип маркера, то генерируемый тип - это вложенный тип, на который мы надеялись. Это достаточно легко сделать для метапрограммиста шаблона, но TTI упрощает выполнение этого расчета, предоставляя одну из двух метафункций. Эти две метафункции: «boost::tti::valid_member_type» и «boost:::tti::valid_member_metafunction»:
Table 1.4. TTI Nested Type Macro Metafunction Existence
Внутренний элемент |
Макро |
шаблон |
Специфический файл заголовка |
---|---|---|---|
Тип |
Нет |
класс T = класс типа U = (необязательно) тип маркера возвращается = истинно, если тип существует, ложно, если нет. «Существование» определяется тем, не равен ли тип маркерному типу BOOST_TTI_MEMBER_TYPE. |
|
Тип |
Нет |
класс T = возвращает метафункциональный тип = истинно, если существует возвратный «тип» метафункции, ложно, если нет. Существование определяется тем, не равен ли возвращаемый «тип» маркерному типу BOOST_TTI_MEMBER_TYPE. |
В нашей первой метафункции «boost::tti::valid_member_type» первым параметром является возврат «типа» от вызова метафункции, генерируемой BOOST_TTI_MEMBER_TYPE. Если при вызове метафункции был указан определенный пользователем тип маркера, то второй необязательный параметр - это тип маркера, иначе нет необходимости указывать необязательный второй параметр шаблона. Так как тип маркера сохраняется в виде импульса вложенного типа::tti::marker_type, как только мы вызовем метафункцию, генерируемую BOOST_TTI_MEMBER_TYPE Мы всегда можем использовать это в качестве второго параметра шаблона для «boost::tti::valid_member_type».
Вторая метафункция, boost::tti::valid_member_metafunction, облегчает процесс прохождения нашего вложенного типа и типа маркера. Здесь единственным параметром шаблона является вызванная метафункция, генерируемая самим BOOST_TTI_MEMBER_TYPE. Затем он выбирает из вызванной метафункции как обратный «тип», так и вложенный импульс::tti::marker_type для правильного расчета.
Простой пример такой функциональности:
#include <boost/tti/member_type.hpp> struct UDMarkerType { }; BOOST_TTI_MEMBER_TYPE(ANamedType) typedef member_type_ANamedType<EnclosingType> IMType; typedef member_type_ANamedType<EnclosingType,UDMarkerType> IMTypeWithMarkerType;
затем
boost::tti::valid_member_type<IMType::type>::value boost::tti::valid_member_type<IMTypeWithMarkerType::type,IMTypeWithMarkerType::boost_tti_marker_type>::value
или
boost::tti::valid_member_metafunction<IMType>::value boost::tti::valid_member_metafunction<IMTypeWithMarkerType>::value
Это дает нам результат компиляции.
В качестве расширенного примера, учитывая тип T, давайте создадим метафункцию, в которой есть вложенный тип FindType, чей закрытый тип в конечном итоге является T, как представлено следующей структурой:
struct T { struct AType { struct BType { struct CType { struct FindType { }; } }; }; };
В нашем коде TTI мы сначала создаем серию макросов типа участника для каждого из наших вложенных типов:
BOOST_TTI_MEMBER_TYPE(FindType) BOOST_TTI_MEMBER_TYPE(AType) BOOST_TTI_MEMBER_TYPE(BType) BOOST_TTI_MEMBER_TYPE(CType)
Далее мы можем создать типдеф для отражения вложенного типа FindType, который имеет связь, как указано выше, путем инстанцирования наших макрометафункций. Мы должны сделать это в обратном порядке нашей гипотетической «структуры Т» выше, поскольку метафункцияBOOST_TTI_MEMBER_TYPE
берет в качестве параметра шаблона свой ограждающий тип.
typedef typename member_type_FindType < typename member_type_CType < typename member_type_BType < typename member_type_AType < T >::type >::type >::type >::type MyFindType;
Мы можем использовать приведенный выше типдеф для передачи типа FindType одной из наших макрометафункций. Найти Тип может не существовать, но мы не будем генерировать ошибку компилятора при его использовании. Он будет генерировать, если его не существует, возможный сбой, если какая-либо метафункция использует такой тип, возвращает ложное значение во время компиляции.
Например, давайте спросим, есть ли в FindType статические данные, называемые MyData типа «int». Добавим:
BOOST_TTI_HAS_STATIC_MEMBER_DATA(MyData)
Далее мы создаем нашу метафункцию:
has_static_member_data_MyData < MyFindType, int >
Используйте это в нашем метапрограммном коде. Теперь наша метафункция сообщает нам, имеет ли вложенный тип FindType статические данные, называемые MyData типа «int», даже если FindType на самом деле не существует. Если бы мы попытались сделать это с помощью обычной нотации вложенного типа C++, наш метафункциональный код был бы следующим:
has_static_member_data_MyData < typename T::AType::BType::CType::FindType, int >
Но это не удается с ошибкой компилятора, если нет такого вложенного типа, и это именно то, чего мы не хотим в нашем коде метапрограммирования на время компиляции.
В вышеупомянутой метафункции мы спрашиваем, имеет ли FindType статический элемент данных, называемый «MyData», и результат будет «ложным», если либо FindType не существует, либо если он существует, но не имеет статических данных типа «int», называемых «MyData». Ни в одной из этих ситуаций мы не допустим ошибки компилятора.
Мы также можем быть заинтересованы в том, чтобы установить, действительно ли существует глубоко вложенный тип «FindType». Наша метафункция, используя BOOST_TTI_MEMBER_TYPE и повторяя наши макросы сверху, может быть:
BOOST_TTI_MEMBER_TYPE(FindType) BOOST_TTI_MEMBER_TYPE(AType) BOOST_TTI_MEMBER_TYPE(BType) BOOST_TTI_MEMBER_TYPE(CType) BOOST_TTI_HAS_TYPE(FindType) has_type_FindType < typename member_type_CType < typename member_type_BType < typename member_type_AType < T >::type >::type >::type >
Но это дублирует большую часть нашего кода, когда мы генерировали файл типа MyFindType. Вместо этого мы используем функциональность, уже предоставленную «boost::tti::valid_member_type». Используя эту функциональность с типом MyFindType выше, мы создаем нулевую метафункцию:
boost::tti::valid_member_type < MyFindType >
Вместо того, чтобы копировать ту же функциональность с метафункцией «has_type_FindType».
Статья Nested Types раздела Chapter 1. The Type Traits Introspection Library Chapter 1. The Type Traits Introspection Library может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: Chapter 1. The Type Traits Introspection Library ::
реклама |