С++, определен ли тип: предварительное декларирование нужных объектов

от автора

В прошлый раз, мы использовали SFINAE, чтобы понять, есть ли у типа определение, и мы использовали это в сочетании с if constexpr и универсальными лямбда-выражениями, чтобы код мог использовать тип, если он определен, при этом все еще принимаясь компилятором (и отбрасываясь) если тип не определен.

Однако в этом применении существует несколько проблем:

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

Мы можем исправить все три проблемы с помощью одного решения: предварительно объявить тип в нужном пространстве имен.

// awesome.h namespace awesome {   // может или может не содержать   struct special { ... }; }  // ваш код  namespace awesome {   // обеспечить объявление типов, которые мы детерминируем   struct special; } 

После того, как вы это сделали, вам не нужно писать struct, потому что структура была объявлена. Использование ее в качестве параметра типа шаблона в call_if_defined не приведет к созданию нового объявления, поскольку все уже было объявлено. И так как она была объявлена, вы можете получить к ней доступ через ее неквалифицированное имя, ее полное имя пространства имен или через что-либо между ними. Также через псевдоним типа или зависимый тип (к сожалению, они не между).

namespace app {   void foo()   {     call_if_defined<awesome::special>([&](auto* p)     {        // Этот код компилируется только если "awesome::special"        // определен. Создайте локальное имя для "special"        // выведя его из фиктивного параметра.        using special = std::decay_t<decltype(*p)>;         // Теперь можно использовать локальное имя "special" для доступа        // к параметрам "awesome::special".        special::do_something();     });   } } 

Те, кто следил за данной серией статей с самого начала, могли заметить, что метод call_if_defined не совсем совпадает с версией, которую мы написали ранее. Новая версия поддерживает несколько параметров типа и вызывает лямбду, только если определены все типы.

Посмотрим ближе:

template<typename... T, typename TLambda> void call_if_defined(TLambda&& lambda) {   if constexpr ((... && is_complete_type_v<T>)) {     lambda(static_cast<T*>(nullptr)...);   } } 

Двойные скобки в if constexpr ((…)) выглядят странно, но они обязательны. Внешние скобки требуются оператором if constexpr, а внутренние скобки требуются выражением свертки. Выражение свертки расширяется до

  if constexpr (     (is_complete_type_v<T1> &&      is_complete_type_v<T2> &&      ...      is_complete_type_v<Tn>)) 

Вызов лямбды использует расширение пакета параметров:

    lambda(static_cast<T*>(nullptr)...); 

Это расширяется до

    lambda(static_cast<T1*>(nullptr),            static_cast<T2*>(nullptr),            ...,            static_cast<Tn*>(nullptr)); 

где static_cast<T*>(nullptr) повторяется один раз для каждого типа.

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

void foo(Source const& source) {   call_if_defined<special, magic>(     [&](auto* p1, auto* p2)     {       using special = std::decay_t<decltype(*p1)>;       using magic = std::decay_t<decltype(*p2)>;        auto s = source.try_get<special>();       if (s) magic::add_magic(s);     }); } 

C++20 позволяет записать это так:

void foo(Source const& source) {   call_if_defined<special, magic>(     [&]<typename special, typename magic>     (special*, magic*)     {       auto s = source.try_get<special>();       if (s) magic::add_magic(s);     }); } 

что позволяет вам называть тип шаблона, тем самым избавляя вас от необходимости заново извлекать его, играя с std::decay_t.

В следующей статье мы будем использовать эту как трамплин и расширять схему.


Примечание: это четвертая часть основной серии статей, но еще есть и другие части (1,2,3,5). Для нетерпеливых: вот, что нужно скопировать и вставить:

template<typename, typename = void> constexpr bool is_type_complete_v = false;  template<typename T> constexpr bool is_type_complete_v     <T, std::void_t<decltype(sizeof(T))>> = true;  template<typename... T, typename TLambda> void call_if_defined(TLambda&& lambda) {   if constexpr ((... && is_complete_type_v<T>)) {     lambda(static_cast<T*>(nullptr)...);   } }

Кстати, у нас есть классная вакансия

Более десяти лет Havok находится на острие инноваций в разработке игр и интерактивного 3D. Как часть Cognition, команды, отвечающей за HoloLens, мы теперь комбинируем эту экспертизу и силу облака Azure для разработки многих новых захватывающих сервисов, поддерживающих смешанную реальность. Среди них недавно анонсированная служба удаленного рендеринга Azure (Azure Remote Rendering). Мы увлечены совмещением AR, VR и облачных технологий, которые вместе позволяют создавать инновационные практики использования смешанной реальности.

Работа в Havok:

  • Вы будете работать в небольших командах с талантливыми разработчиками
  • У вас будет возможность работать с новыми технологиями на самых разных аппаратных платформах и устройствах
  • Вы будете работать над решением сложных технических задач, имеющих огромные перспективы
  • Вы будете сотрудничать с крутыми командами по всему миру

Обязанности

  • Проектировать, разрабатывать и тестировать высококачественный, эффективный и чистый мультиплатформенный С++ код
  • Разрабатывать хорошо-масштабируемые сервисы Azure
  • Работать напрямую с внутренними и внешними заказчиками, чтобы стимулировать разработку продукта

Квалификации

  • Навыки программирования и отладки на C++
  • Умение работать в команде с общим кодом
  • Опыт работы с облачными и распределенными сервисными технологиями (например, Azure Batch, Azure Blob Storage, Docker, Telemetry)

Будет плюсом

  • C#, ASP.Net, JavaScript, TypeScript, React
  • Unity, Unreal или связанные игровые движки
  • Опыт в интерактивном 3D, AR или VR
  • Сетевые и серверные сервисы
  • Оптимизация производительности

Вы можете узнать больше и подать свою заявку здесь.


ссылка на оригинал статьи https://habr.com/ru/company/microsoft/blog/459787/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *