C ++, ob der Typ definiert ist: vorläufige Deklaration der notwendigen Objekte

Beim letzten Mal haben wir SFINAE verwendet, um herauszufinden, ob ein Typ eine Definition hat, und wir haben sie in Kombination mit if constexpr und generischen Lambda-Ausdrücken verwendet, damit der Code den Typ verwenden kann, wenn er definiert ist, während er vom Compiler weiterhin akzeptiert wird (und verworfen), wenn der Typ nicht definiert ist.

Bei dieser Anwendung gibt es jedoch mehrere Probleme:

  • Jedes Mal, wenn Sie eine struct schreiben müssen.
  • Wenn der Typ nicht vorhanden ist, wird dieser Typ beim Benennen im aktuellen Namespace und nicht in dem Namespace eingegeben, in dem der Typ sein soll.
  • Sie müssen eine struct mit einem nicht qualifizierten Namen verwenden. Sie können damit nicht nach einem Typ suchen, den Sie nicht in den aktuellen Namespace importiert haben.

Wir können alle drei Probleme mit einer Lösung beheben: Deklarieren Sie zuerst den Typ im gewünschten Namespace.



 // awesome.h namespace awesome { //      struct special { ... }; } //   namespace awesome { //   ,    struct special; } 

Nachdem Sie dies getan haben, müssen Sie keine Struktur schreiben, da die Struktur deklariert wurde. Die Verwendung als Vorlagentypparameter in call_if_defined führt nicht zur Erstellung einer neuen Deklaration, da bereits alles deklariert wurde. Und da sie deklariert wurde, können Sie über ihren unqualifizierten Namen, ihren vollständigen Namespace-Namen oder über alles dazwischen auf sie zugreifen. Auch über einen Typalias oder einen abhängigen Typ (leider liegen sie nicht dazwischen).

 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(); }); } } 

Diejenigen, die diese Artikelserie von Anfang an verfolgt haben, haben möglicherweise bemerkt, dass die Methode call_if_defined nicht genau mit der Version übereinstimmt, die wir zuvor geschrieben haben. Die neue Version unterstützt mehrere Typparameter und ruft nur dann ein Lambda auf, wenn alle Typen definiert sind.

Schauen wir uns das genauer an:

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

Die doppelten Klammern in if constexpr ((...)) sehen seltsam aus, sind aber erforderlich. Externe Klammern werden von der if constexpr , und interne Klammern werden von einem Faltungsausdruck benötigt. Der Faltungsausdruck erweitert sich zu

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

Der Lambda-Aufruf verwendet die Parameterpaket-Erweiterung :

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

Es erweitert sich zu

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

Dabei wird static_cast<T*>(nullptr) für jeden Typ einmal wiederholt.

Wie bereits erwähnt, können wir diese Funktion verwenden, um das Lambda aufzurufen, wenn alle Typen definiert sind:

 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); }); } 

Mit C ++ 20 können Sie es folgendermaßen schreiben:

 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); }); } 

Auf diese Weise können Sie den Typ der Vorlage benennen, sodass Sie sie beim Spielen mit std::decay_t erneut extrahieren std::decay_t .

Im nächsten Artikel werden wir dies als Sprungbrett verwenden und die Schaltung erweitern.



Hinweis : Dies ist der vierte Teil der Hauptartikelserie, es gibt jedoch noch andere Teile ( 1 , 2 , 3 , 5 ). Für Ungeduldige: Folgendes müssen Sie kopieren und einfügen:

 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)...); } } 

Übrigens haben wir einen coolen Job


Seit mehr als einem Jahrzehnt ist Havok führend bei Innovationen in der Spieleentwicklung und im interaktiven 3D. Als Teil von Cognition, dem HoloLens-Team, kombinieren wir jetzt dieses Know-how und die Leistungsfähigkeit der Azure-Cloud, um viele aufregende neue Mixed-Reality-Dienste zu entwickeln. Darunter befindet sich der kürzlich angekündigte Azure Remote Rendering-Dienst. Wir kombinieren leidenschaftlich AR-, VR- und Cloud-Technologien, die es uns ermöglichen, mithilfe der gemischten Realität innovative Praktiken zu entwickeln.

Jobs bei Havok:

  • Sie arbeiten in kleinen Teams mit talentierten Entwicklern
  • Sie haben die Möglichkeit, mit neuen Technologien auf einer Vielzahl von Hardwareplattformen und -geräten zu arbeiten.
  • Sie arbeiten an der Lösung komplexer technischer Probleme mit guten Aussichten
  • Sie werden mit coolen Teams auf der ganzen Welt zusammenarbeiten.

Verantwortlichkeiten


  • Entwerfen, entwickeln und testen Sie hochwertigen, effizienten und sauberen C ++ - Code für mehrere Plattformen
  • Entwickeln Sie gut skalierbare Azure-Dienste
  • Arbeiten Sie direkt mit internen und externen Kunden zusammen, um die Produktentwicklung anzuregen

Qualifikationen


  • C ++ - Programmier- und Debugging-Kenntnisse
  • Fähigkeit, in einem Team mit einem gemeinsamen Code zu arbeiten
  • Erfahrung mit Cloud- und verteilten Servicetechnologien (z. B. Azure Batch, Azure Blob-Speicher, Docker, Telemetrie)

Wird ein Plus sein


  • C #, ASP.Net, JavaScript, TypeScript, Reagieren
  • Unity, Unreal oder verwandte Spiel-Engines
  • Erleben Sie interaktives 3D, AR oder VR
  • Netzwerk- und Serverdienste
  • Leistungsoptimierung

Sie können mehr erfahren und Ihre Bewerbung hier oder über LinkedIn einreichen.

Source: https://habr.com/ru/post/de459787/


All Articles