在C ++中检测是否定义了类型:预先声明要探测的内容

Last time, we used SFINAE to detect whether a type had a definition, and we used that in combination with  上一次 ,我们使用SFINAE来检测类型是否具有定义,并将其与 if constexpr and generic lambdas so that code could use the type if it is defined, while still being accepted by the compiler (and being discarded) if the type is not defined. if constexpr和通用lambdas结合使用,以便代码可以使用该类型(如果已定义),同时仍被编译器接受(并被丢弃) )(如果未定义类型)。

However, our usage had a few issues, some minor annoyance, some more frustrating.

但是,我们的用法存在一些问题,有些烦人,有些令人沮丧。

  • You had to say struct all the time.

    您必须一直说struct

  • If the type didn’t exist, the act of naming it caused the type to be injected into the current namespace, not the namespace you expected the type to be in.

    如果类型不存在,则将其命名会导致将类型注入到当前名称空间中,而不是您希望类型所位于的名称空间中。

  • You must use the struct technique with an unqualified name. You can’t use it to probe a type that you didn’t import into the current namespace.

    您必须使用具有非限定名称的struct技术。 您不能使用它来探测未导入当前名称空间的类型。

We can fix all three of the problems with a single solution: Predeclare the type in the desired namespace.

我们可以用一个解决方案解决所有三个问题:在所需的名称空间中预先声明类型。

// awesome.h
namespace awesome
{
  // might or might not contain
  struct special { ... };
}

// your code

namespace awesome
{
  // ensure declarations for types we
  // conditionalize on.
  struct special;
}

Once you’ve done this, you don’t need to say struct because the struct definitely has been declared. Your use of it as a template type parameter in call_if_defined will not create a new declaration, because it has already been declared. And since it has been declared, you can access it via its unqualified name, its full namespace name, or anything in between. Also a type alias or dependent type. (Sorry, those aren’t in between.)

完成此操作后,无需说struct因为struct肯定已经声明了。 在call_if_defined中将其用作模板类型参数将不会创建新的声明,因为已经声明了它。 并且由于已经声明了它,因此您可以通过其非限定名称,完整的名称空间名称或介于两者之间的任何名称来访问它。 也是类型别名或从属类型。 (抱歉,它们不在中间。)

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

For those who have been following the series from the beginning, you may have noticed that the call_if_defined method is not quite the same as the version we wrote earlier. The new version supports multiple type parameters and calls the lambda only if all of the types are defined.

对于那些从一开始就遵循该系列的人,您可能已经注意到call_if_defined方法与我们先前编写的版本不太相同。 新版本支持多个类型参数,并且仅在定义所有类型时才调用lambda。

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

The double-parentheses in the if constexpr ((...)) look weird, but they’re required. The outer parentheses are required by the if constexpr statement, and the inner parentheses are required by the fold expression. The fold expression expands to

if constexpr((...))中的双括号看起来很奇怪,但是是必需的。 if constexpr语句需要外部括号,而fold表达式需要内部括号。 fold表达式扩展为

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

The invoke of the lambda uses a parameter pack expansion:

lambda的调用使用参数包扩展

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

This expands to

这扩展到

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

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

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

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

如前所述,如果定义了所有类型,则可以使用此函数来调用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 allows you to write this as

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

which lets you name the template type, thereby saving you the trouble of having to re-derive it by playing std::decay_t games.

这样您就可以命名模板类型,从而省去了通过玩std::decay_t游戏重新派生模板的麻烦。

Next time, we’ll use this as a springboard and extend the pattern. 下次 ,我们将其用作跳板并扩展图案。

注意那些通过搜索引擎到达这里的人 (Note to those who got here via a search engine)

: This is the last part of the core portion of the series, but there are still parts to come. For the impatient, here’s the stuff to copy-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 vacancy [Dublin])

Havok has been at the cutting edge of innovation in game development and interactive 3D for over a decade. As part of Cognition, the team responsible for HoloLens, we are now combining that expertise with the power of the Azure Cloud to develop many new exciting services driving Mixed Reality experiences such as the recently announced Azure Remote Rendering service. We are passionate about the convergence of AR, VR and cloud technologies to enable the creation of ground-breaking Mixed Reality experiences.

十多年来,Havok一直处于游戏开发和交互式3D创新的最前沿。 作为负责HoloLens的团队Cognition的一部分,我们现在将专业知识与Azure云的功能相结合,以开发许多新的令人兴奋的服务来推动混合现实体验,例如最近宣布的Azure远程渲染服务。 我们对增强现实,虚拟现实和云技术的融合充满热情,能够创造出开创性的混合现实体验。

在Havok工作: (Working in Havok: )

  • You will work in small focused teams with talented developers

    您将与专注于开发的小型团队一起工作
  • You will have the opportunity to work with new technologies on a diverse range of cutting-edge hardware platforms and devices

    您将有机会在各种最新的硬件平台和设备上使用新技术。
  • You will work on solving challenging technical problems with wide scope

    您将广泛解决具有挑战性的技术问题
  • You will collaborate with talented teams around the world

    您将与世界各地的优秀团队合作
职责范围 (Responsibilities)
  • Design, develop, test and deliver high quality, efficient and clean multiplatform C++ code

    设计,开发,测试和交付高质量,高效和干净的多平台C ++代码
  • Develop highly scalable Azure services

    开发高度可扩展的Azure服务
  • Work directly with internal and external customers to drive product development

    直接与内部和外部客户合作以推动产品开发
资格 (Qualifications)
  • C++ coding and debugging skills

    C ++编码和调试技巧
  • An ability to work in a team environment on a shared code base

    在共享代码库中的团队环境中工作的能力
  • Experience with cloud and distributed services technologies (e.g. Azure Batch, Azure Blob Storage, Docker, Telemetry)

    具有云和分布式服务技术(例如Azure Batch,Azure Blob存储,Docker,遥测)的经验
奖励积分 (Bonus points)

There are plenty of other skills that aren’t required, but that are valuable across the team and these include:

还有许多其他技能不是必需的,但它们在整个团队中都很有价值,其中包括:

  • C#, ASP.Net, JavaScript, TypeScript, React

    C#,ASP.Net,JavaScript,TypeScript,React
  • Unity, Unreal or related game engines

    Unity,虚幻或相关的游戏引擎
  • Experience in interactive 3D, AR or VR

    具有交互式3D,AR或VR的经验
  • Networking and backend services

    网络和后端服务
  • Performance optimization

    性能优化

You can get more information and submit your CV here.

您可以在此处获取更多信息并提交简历。

翻译自: https://habr.com/en/company/microsoft/blog/459834/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值