Erkennen in C ++, ob ein Typ definiert ist: Vordeklarieren von Dingen, die Sie prüfen möchten

Beim letzten Mal haben wir SFINAE verwendet, um festzustellen, ob ein Typ eine Definition hat, und wir haben diese in Kombination mit if constexpr und generischen Lambdas verwendet, damit Code den Typ verwenden kann, wenn er definiert ist, während er vom Compiler noch akzeptiert wird (und verworfen wird) ) wenn der Typ nicht definiert ist.

Unsere Verwendung hatte jedoch einige Probleme, einige geringfügige Belästigungen, andere frustrierender.

  • Man musste die ganze Zeit struct sagen.
  • Wenn der Typ nicht vorhanden war, wurde er durch die Benennung in den aktuellen Namespace eingefügt, nicht in den Namespace, in dem sich der Typ befinden sollte.
  • Sie müssen die struct mit einem nicht qualifizierten Namen verwenden. Sie können damit keinen Typ prüfen, den Sie nicht in den aktuellen Namespace importiert haben.

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



 // awesome.h namespace awesome { // might or might not contain struct special { ... }; } // your code namespace awesome { // ensure declarations for types we // conditionalize on. struct special; } 

Sobald Sie dies getan haben, müssen Sie nicht mehr struct sagen, da die struct definitiv deklariert wurde. call_if_defined es als Vorlagentypparameter in call_if_defined wird keine neue Deklaration erstellt, da diese bereits deklariert wurde. Und da es deklariert wurde, können Sie über seinen nicht qualifizierten Namen, seinen vollständigen Namespace-Namen oder irgendetwas dazwischen darauf zugreifen. Auch ein Typalias oder ein abhängiger Typ. (Sorry, die liegen nicht dazwischen.)

 namespace app { void foo() { call_if_defined<awesome::special>([&](auto* p) { // this code is compiled only if "awesome::special" // is defined. Create a local name for "special" // by inferring it from the dummy parameter. using special = std::decay_t<decltype(*p)>; // You can now use the local name "special" to access // the features of "awesome::special". special::do_something(); }); } } 

Für diejenigen, die die Serie von Anfang an verfolgt haben, ist möglicherweise aufgefallen, dass die Methode call_if_defined nicht ganz mit der Version call_if_defined , die wir zuvor geschrieben haben. Die neue Version unterstützt mehrere Typparameter und ruft das Lambda nur 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 Doppelklammern in if constexpr ((...)) sehen seltsam aus, sind aber erforderlich. Die äußeren Klammern werden von der if constexpr Anweisung benötigt, und die inneren Klammern werden vom fold-Ausdruck benötigt . Der Fold-Ausdruck wird auf erweitert

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

Der Aufruf des Lambda verwendet eine Parameterpack-Erweiterung :

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

Dies erweitert sich auf

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

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

Wie bereits erwähnt, können wir mit dieser Funktion ein Lambda aufrufen, 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); }); } 

In C ++ 20 können Sie dies als 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 Vorlagentyp benennen und sich so die Mühe ersparen, ihn durch Spielen von std::decay_t Spielen erneut ableiten zu std::decay_t .

Nächstes Mal werden wir dies als Sprungbrett verwenden und das Muster erweitern.



Hinweis für diejenigen, die über eine Suchmaschine hierher gekommen sind : Dies ist der letzte Teil des Kernteils der Serie, aber es werden noch Teile folgen. Für die Ungeduldigen ist hier das Zeug zum 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 eine coole Stelle [Dublin]


Havok ist seit über einem Jahrzehnt auf dem neuesten Stand der Innovation in der Spieleentwicklung und im interaktiven 3D. Als Teil von Cognition, dem für HoloLens verantwortlichen Team, kombinieren wir dieses Know-how jetzt mit der Leistungsfähigkeit der Azure Cloud, um viele neue aufregende Dienste zu entwickeln, die Mixed Reality-Erlebnisse wie den kürzlich angekündigten Azure Remote Rendering-Dienst ermöglichen. Wir sind begeistert von der Konvergenz von AR-, VR- und Cloud-Technologien, um bahnbrechende Mixed Reality-Erlebnisse zu schaffen.

Arbeiten in Havok:

  • Sie arbeiten in kleinen, fokussierten Teams mit talentierten Entwicklern
  • Sie haben die Möglichkeit, mit neuen Technologien auf einer Vielzahl von hochmodernen Hardwareplattformen und -geräten zu arbeiten
  • Sie arbeiten an der Lösung herausfordernder technischer Probleme mit großem Umfang
  • Sie werden mit talentierten Teams auf der ganzen Welt zusammenarbeiten

Verantwortlichkeiten


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

Qualifikationen


  • C ++ - Codierungs- und Debugging-Kenntnisse
  • Die Fähigkeit, in einer Teamumgebung auf einer gemeinsam genutzten Codebasis zu arbeiten
  • Erfahrung mit Cloud- und verteilten Servicetechnologien (z. B. Azure Batch, Azure Blob-Speicher, Docker, Telemetrie)

Bonuspunkte


Es gibt viele andere Fähigkeiten, die nicht erforderlich sind, aber im gesamten Team wertvoll sind. Dazu gehören:

  • C #, ASP.Net, JavaScript, TypeScript, Reagieren
  • Unity, Unreal oder verwandte Spiel-Engines
  • Erfahrung in interaktivem 3D, AR oder VR
  • Netzwerk- und Backend-Dienste
  • Leistungsoptimierung

Weitere Informationen und Ihren Lebenslauf erhalten Sie hier .

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


All Articles