Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Nested Types

Boost , Chapter 1. The Type Traits Introspection Library , Chapter 1. The Type Traits Introspection Library

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

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

Первый Я объясню синтаксис и использование этой функции, а затем причину, по которой она существует в библиотеке.

Функциональность — это метафункция, созданная макросом.Boost_TTI_MEMBER_TYPE. Макро принимает один параметр, который является названием вложенного типа. Мы будем называть это «названным типом». Макро генерирует метафункцию под названиемmember_type_Имя_типкоторый, пройдя ограждающий тип, возвращает названный тип, если он существует, а другой тип маркера, если он не существует.

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

Его общее объяснение дается как:

Table 1.3. TTI Nested Type Macro Metafunction

Внутренний элемент

Макро

шаблон

Специфический файл заголовка

Тип

BOOST_TTI_MEMBER_TYPE(имя)

member_type_'name'

класс T = прилагающийся класс типа U = (необязательно) тип маркера

возвращается = тип 'name', если он существует, иначе тип маркера, как тип typedef'.

Вызванная метафункция также содержит тип маркера в виде типдефа «boost_tti_marker_type». Это делается для удобства, чтобы не пришлось запоминать тип маркера.

member_type.hpp


Тип маркера является чисто факультативным. Если не указан тип внутренней библиотеки 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 Теперь мы можем ответить на вопрос, почему эта функциональность для создания «типа» существует при поиске вложенного типа замкнутого типа.

The problem

Метафункции, генерируемые макросами 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Заявления выбора типа, чтобы добраться до некоторого конечного состояния, когда мы знаем, что можем генерировать код времени компиляции, который мы хотим.

The solution

Решение, данное BOOST_TTI_MEMBER_TYPE, заключается в том, что мы можем создать тип в качестве возврата от нашей метафункции, который является тем же типом, что и вложенный тип, если он существует, или какой-либо другой тип маркера, если он не существует, а затем работать с этим возвращенным типом, не создавая ошибки компилятора. Если бы нам пришлось использовать синтаксис «T::InnerType», чтобы указать наш тип, где «T» представляет собой вложенный тип и «InnerType» наш вложенный тип, и не было бы вложенного типа «InnerType» в вложенном типе «T», компилятор немедленно дал бы нам ошибку.

Используя BOOST_TTI_MEMBER_TYPE У нас есть тип, с которым можно работать, даже если такого типа на самом деле не существует. Естественно, если тип не существует, то тип, с которым мы должны работать, будучи маркерным типом, как правило, не будет выполнять другие функции, которые мы хотим от него. Это хорошо и, как правило, дает правильные результаты при дальнейшем использовании этого типа при программировании метафункций. Иногда тип маркера, полученный TTI, когда наш вложенный тип не существует, не достаточен для дальнейшего программирования метафункций. В этом редком случае конечный пользователь может создать свой собственный тип маркера, который будет использоваться, если вложенный тип не существует. В любом случае, существует ли вложенный тип, используется ли тип маркера по умолчанию TTI или используется тип маркера конечного пользователя, метапрограммирование шаблона может продолжаться без проблемы компиляции. Кроме того, эта шкала лучше, чем постоянная проверка наличия вложенного типа через BOOST_TTI_HAS_TYPE в сложном шаблонном метапрограммном коде.

Checking if the member type exists

Как только мы используем BOOST_TTI_MEMBER_TYPE для создания вложенного типа, если он существует, мы обычно используем этот тип в дальнейшем программировании метафункций. Иногда, учитывая тип, который мы генерируем, мы захотим спросить, действительно ли тип является нашим вложенным типом или типом маркера. По сути, мы спрашиваем, является ли генерируемый тип маркерным или нет. Если это тип маркера, то генерируемый тип не является вложенным типом, на который мы надеялись. Если это не тип маркера, то генерируемый тип - это вложенный тип, на который мы надеялись. Это достаточно легко сделать для метапрограммиста шаблона, но TTI упрощает выполнение этого расчета, предоставляя одну из двух метафункций. Эти две метафункции: «boost::tti::valid_member_type» и «boost:::tti::valid_member_metafunction»:

Table 1.4. TTI Nested Type Macro Metafunction Existence

Внутренний элемент

Макро

шаблон

Специфический файл заголовка

Тип

Нет

boost::tti::valid_member_type

класс T = класс типа U = (необязательно) тип маркера

возвращается = истинно, если тип существует, ложно, если нет. «Существование» определяется тем, не равен ли тип маркерному типу BOOST_TTI_MEMBER_TYPE.

member_type.hpp

Тип

Нет

boost::tti::valid_member_metafunction

класс T = возвращает метафункциональный тип

= истинно, если существует возвратный «тип» метафункции, ложно, если нет. Существование определяется тем, не равен ли возвращаемый «тип» маркерному типу BOOST_TTI_MEMBER_TYPE.

member_type.hpp


В нашей первой метафункции «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

Это дает нам результат компиляции.

An extended nested type example

В качестве расширенного примера, учитывая тип 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».


PrevUpHomeNext

Статья 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 ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 08:49:10/0.0092830657958984/0