C ++,是否定义了类型:必要对象的初步声明

上一次 ,我们使用SFINAE来确定类型是否具有定义,并将其与if constexpr和泛型lambda表达式结合使用,以便代码可以使用该类型(如果已定义),同时仍被编译器接受(并且丢弃)(如果未定义类型)。

但是,此应用程序存在一些问题:

  • 每次您需要编写一个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方法与我们之前编写的版本不太匹配。 新版本支持多个类型参数,并且仅在定义所有类型时才调用lambda。

让我们仔细看看:

 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调用使用参数包扩展名

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

它扩展到

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

其中,每种类型的static_cast<T*>(nullptr)重复一次。

如前所述,如果定义了所有类型,则可以使用此函数来调用lambda:

 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创新的最前沿。 作为HoloLens团队Cognition的一部分,我们现在将这种专业知识与Azure云的功能相结合,以开发许多令人兴奋的新型混合现实服务。 其中包括最近宣布的Azure远程渲染服务。 我们热衷于结合AR,VR和云技术,这些技术使我们能够使用混合现实创建创新实践。

Havok的职位:

  • 您将与有才能的开发人员组成小型团队
  • 您将有机会在各种硬件平台和设备上使用新技术。
  • 您将致力于解决具有广阔前景的复杂技术问题
  • 您将与世界各地的优秀团队合作。

职责范围


  • 设计,开发和测试高质量,高效和干净的多平台C ++代码
  • 开发可扩展的Azure服务
  • 直接与内部和外部客户合作以刺激产品开发

资历


  • C ++编程和调试技巧
  • 具有通用代码的团队合作能力
  • 具有云和分布式服务技术的经验(例如Azure Batch,Azure Blob存储,Docker,遥测)

将是一个加号


  • C#,ASP.Net,JavaScript,TypeScript,React
  • Unity,虚幻或相关的游戏引擎
  • 体验互动式3D,AR或VR
  • 网络和服务器服务
  • 性能优化

您可以了解更多信息,并在此处或通过LinkedIn提交申请。

Source: https://habr.com/ru/post/zh-CN459787/


All Articles