📜 ⬆️ ⬇️

C ++, whether the type is defined: preliminary declaration of the necessary objects

Last time , we used SFINAE to figure out whether a type has a definition, and we used this in combination with if constexpr and universal lambda expressions so that the code can use the type if it is defined while still being adopted by the compiler (and discarded) if the type is not defined.

However, there are several problems with this application:


We can fix all three problems with one solution: pre-declare the type in the desired namespace.
')


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

After you have done this, you do not need to write a struct because the structure has been declared. Using it as a template type parameter in call_if_defined will not create a new ad, since everything has already been announced. And since she was declared, you can access her through her unqualified name, her full namespace name, or something in between. Also through the type alias or dependent type (unfortunately, they are not between).

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

Those who followed this series of articles from the very beginning might have noticed that the call_if_defined method call_if_defined not quite coincide with the version we wrote earlier. The new version supports several type parameters and causes lambda only if all types are defined.

Let's take a closer look:

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

Double brackets in if constexpr ((...)) look weird, but they are required. The outer brackets are required by the if constexpr operator, and the inner brackets are required by the convolution expression . The convolution expression expands to

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

The lambda call uses a parameter package extension :

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

It expands to

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

where static_cast<T*>(nullptr) repeated once for each type.

As I noted earlier, we can use this function to call lambda if all types are defined:

 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 allows you to write it like this:

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

which allows you to call the type of the template, thereby eliminating the need to re-extract it, playing with std::decay_t .

In the next article, we will use this as a springboard and expand the circuit.



Note : This is the fourth part of the main series of articles, but there are also other parts ( 1 , 2 , 3 , 5 ). For impatient: here's what you need to copy and paste:

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

By the way, we have a cool job.


For over a decade, Havok has been at the forefront of innovation in game development and interactive 3D. As part of Cognition, the HoloLens team, we are now combining this expertise with the power of the Azure cloud to develop many exciting new services that support mixed reality. Among them is the recently announced Azure Remote Rendering service. We are passionate about combining AR, VR and cloud technologies, which together allow us to create innovative practices of using mixed reality.

Jobs at Havok:


Duties



Qualifications



It will be a plus



You can learn more and submit your application here or through LinkedIn .

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


All Articles