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

General Functionality

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. Это достигается за счет создания метафункций, которые можно использовать во время компиляции, используя макросы C++. Каждая из созданных метафункций возвращает значение постоянной крутизны времени компиляции, которое отвечает на один из вышеуказанных вопросов во время компиляции. Когда конкретный элемент выше существует, значение «истинно» или, точнее, «повышать»::mpl::true_, в то время как, если элемент не существует, значение «ложно» или, точнее, «повышать»::mpl::false_. В любом случае тип этого значения является бустером::mpl::bool_.

Это постоянное значение в терминологии библиотеки Boost MPL называется «интегральной постоянной оберткой», а генерируемая метафункция называется «цифровой метафункцией». Результаты вызова метафункции могут быть переданы другим метафункциям для выбора типа, наиболее популярными из которых являются операторы с булевым значением в библиотеке Boost MPL.

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

Все макросы начинаются с префикса BOOST_TTI_, создают свои метафункции в качестве шаблонов классов в любом объеме, который пользователь вызывает макрос, и бывают двух форм:

  1. В простейшей макроформе, которую я называю простой макроформой, «имя» внутреннего элемента используется непосредственно для создания имени метафункции, а также служит «имя» для самоанализа. При генерации имени метафункции из имени макроса удаляется префикс BOOST_TTI_, остальное имя макроса изменяется на нижний регистр, и добавляется подчеркивание («_»), за которым следует «имя». Например, для макро BOOST_TTI_HAS_TYPE(MyType) Имя метафункции has_type_MyType и оно будет искать внутренний тип под названием MyType.
  2. В более сложной макроформе, которую я называю сложной макроформой, макрос начинается с BOOST_TTI_TRAIT_ и в качестве первого параметра пропускается имя «черты», а вторым параметром — «имя» внутреннего элемента. Название черты служит исключительно для того, чтобы полностью назвать метафункцию в любой области применения макроса. Например, для макро BOOST_TTI_TRAIT_HAS_TYPE(MyTrait,MyType) имя метафункции MyTrait и она будет искать внутренний тип под названием MyType.

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

В последующей документации все макрометафункции будут называться по их простому названию формы, но помните, что вместо них всегда можно использовать сложную форму. Сложная форма полезна всякий раз, когда при использовании простой формы можно создать дублирующее имя в одном и том же пространстве имён, тем самым нарушая правило одного определения C++.

Macro Metafunction Name Generation

Для простой макроформы, несмотря на то, что довольно легко запомнить алгоритм, с помощью которого называется генерируемая метафункция, TTI также предоставляет для каждой макрометафункции соответствующий макрос «наименования», который может использовать конечный пользователь и единственной целью которого является расширение до имени метафункции. Макро-именование для каждой макрометафункции имеет форму: «соответствующий-макро»_GEN(имя).

Например, BOOST_TTI_HAS_TYPE (MyType) создает метафункцию, которая ищет вложенный тип под названием «MyType» в некотором закрытом типе. Название генерируемой метафункции, учитывая приведенное выше правило, «has_type_MyType». Соответствующий макрос BOOST_TTI_HAS_TYPE_GEN, в нашем примере называемый BOOST_TTI_HAS_TYPE_GEN (MyType), расширяется до того же имени «has_type_MyType». Эти макросы, генерирующие имена, для каждого из макросов, генерирующих метафункции, являются просто удобством для конечных пользователей, которые находят их использование проще, чем запоминание правила генерации имен, приведенного выше.

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

Правило, чтобы избежать этой проблемы:

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

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

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

Следуя этим двум простым правилам, вы избегаете имен с двойным подчеркиванием, генерируемым TTI.

Reusing the named metafunction

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

В качестве одного из примеров рассмотрим два разных типа, называемые «Атип» и «БТип», для каждого из которых мы хотим определить, существует ли внутренний тип, называемый «Внутренний Тип». Для обоих этих типов нам нужно только создать одну макрометафункцию в текущем объеме, используя:

BOOST_TTI_HAS_TYPE(InnerType)

Теперь у нас есть метафункция, которая является шаблоном класса C++, в текущем объеме, идентификатор C++ которого имеет_type_InnerType. Мы можем использовать эту же метафункцию, чтобы интроспектировать существование вложенного типа «Внутренний тип» в «Атипе» или «Бтипе» во время компиляции. Хотя синтаксис для этого еще не объяснен, я приведу его здесь, чтобы вы могли увидеть, как «has_type_InnerType» используется повторно:

  1. «has_type_InnerType::value» — это постоянная времени компиляции, сообщающая нам, является ли «InnerType» типом, который вложен в «AType».
  2. «has_type_InnerType::value» — это постоянная времени компиляции, сообщающая нам, является ли «InnerType» типом, который вложен в «BType».

В качестве другого примера повторного использования метафункции рассмотрим один тип, называемый «CType», для которого мы хотим определить, имеет ли он одну из двух перегруженных функций-членов с тем же названием «AMemberFunction», но с различными функциональными подписями «int (int)» и «double (long)». Для обеих этих функций необходимо создать только одну макро-метафункцию в текущем объеме, используя:

BOOST_TTI_HAS_MEMBER_FUNCTION(AMemberFunction)

Теперь у нас есть метафункция, которая является шаблоном класса C++, в текущем объеме, идентификатор C++ которого имеет_member_function_AMemberFunction. Мы можем использовать эту же метафункцию, чтобы интроспектировать существование функции-члена «AMemberFunction» с подписью функции «int (int)» или «double (long)» в «CType» во время компиляции. Хотя синтаксис для этого еще не объяснен, я дам его здесь, чтобы вы могли увидеть, как «has_type_InnerType» используется повторно:

  1. «has_member_function_AMemberFunction >::value» — это постоянная времени компиляции, сообщающая нам, является ли «AMemberFunction» функцией-членом типа «CType», чья подпись функции «int (int)».
  2. «has_member_function_AMemberFunction >::value» — это постоянная времени компиляции, сообщающая нам, является ли «AMemberFunction» функцией-членом типа «CType», чья подпись функции «двойная (длинная)».

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

Avoiding ODR violations

Макрометафункции TTI генерируются непосредственно в замкнутом пространстве, в котором задействован соответствующий макрос. Это может быть любой объем C++, в котором может быть указан шаблон класса. В пределах этой области охвата имя генерируемой метафункции должно быть уникальным или C++. Нарушение ODR (правила одного определения). Это чрезвычайно важно помнить, особенно когда объем может происходить в более чем одном блоке перевода, что относится к пространствам имен и глобальному охвату.

Из-за ODR и того, как простое имя метафункции макроформы напрямую зависит от внутреннего элемента и названия элемента, который подвергается интроспекции, программист, использующий макросы TTI, должен генерировать метафункции, чтобы избежать ODR в модуле (приложении или библиотеке). Есть несколько общих методов для этого:

  1. Создавайте уникальные имена пространства имен, в которых генерируются макрометафункции и/или генерируются макрометафункции в областях C++, которые не могут распространяться на единицы перевода. Наиболее очевидным примером этого является класс C++.
  2. Используйте сложную макроформу, чтобы конкретно назвать созданную метафункцию, чтобы обеспечить уникальное имя.
  3. Избегайте использования макросов TTI в глобальном масштабе.

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

TTI также оставляет за собой не только имя, генерируемое макрометафункцией, но и любую последовательность идентификаторов C++, которая начинается с этого имени. Другими словами, если метафункция, генерируемая TTI, называется MyMetafunction с использованием сложной макроформы, не создавайте конструкцию C++ с идентификатором, начинающимся с MyMetaFunction, например MyMetaFunction_Enumeration или MyMetaFunctionHelper. Все имена, начинающиеся с имени метафункции в текущей области, должны рассматриваться вне пределов для программиста, использующего TTI.


PrevUpHomeNext

Статья General Functionality раздела 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-19 22:06:00/0.012300968170166/1