上一次 ,我们使用SFINAE来检测类型是否具有定义,并将其与
if constexpr
和泛型lambda结合使用,以便代码可以使用该类型(如果已定义),同时仍被编译器接受(并被丢弃) )(如果未定义类型)。
但是,我们的用法存在一些问题,有些烦人,有些令人沮丧。
- 您必须一直说
struct
。 - 如果类型不存在,则将其命名的行为会将类型注入到当前名称空间中,而不是您希望类型所位于的名称空间中。
- 您必须使用具有非限定名称的
struct
技术。 您不能使用它来探测未导入当前名称空间的类型。
我们可以用一个解决方案解决所有三个问题:在所需的名称空间中预先声明类型。

一旦完成此操作,就不必说
struct
因为struct肯定已经声明了。 在
call_if_defined
中将其用作模板类型参数将不会创建新的声明,因为已经声明了它。 并且由于已经声明了它,因此您可以通过其非限定名称,其完整名称空间名称或介于两者之间的任何名称来访问它。 也是类型别名或从属类型。 (抱歉,它们不在中间。)
namespace app { void foo() { call_if_defined<awesome::special>([&](auto* p) {
对于那些从一开始就遵循该系列的人,您可能已经注意到
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
语句需要外部括号,而
fold表达式需要内部括号。 fold表达式扩展为
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
游戏重新派生模板的麻烦。
下次 ,我们将其用作跳板并扩展图案。
请注意那些通过搜索引擎到达此处的人 :这是本系列核心部分的最后一部分,但仍有部分内容要讲。 对于不耐烦的人,以下是可复制粘贴的内容:
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远程渲染服务。 我们对增强现实,虚拟现实和云技术的融合充满激情,希望能够创造出开创性的混合现实体验。
在Havok工作:- 您将与专注于开发的小型团队一起工作
- 您将有机会在各种尖端的硬件平台和设备上使用新技术。
- 您将致力于广泛解决具有挑战性的技术问题
- 您将与世界各地的优秀团队合作
职责范围
- 设计,开发,测试和交付高质量,高效和干净的多平台C ++代码
- 开发高度可扩展的Azure服务
- 直接与内部和外部客户合作以推动产品开发
资历
- C ++编码和调试技巧
- 在共享代码库中的团队环境中工作的能力
- 具有云和分布式服务技术(例如Azure批处理,Azure Blob存储,Docker,遥测)的经验
奖励积分
还有许多其他技能不是必需的,但它们在整个团队中都很有价值,其中包括:
- C#,ASP.Net,JavaScript,TypeScript,React
- Unity,虚幻或相关的游戏引擎
- 具有交互式3D,AR或VR的经验
- 网络和后端服务
- 性能优化
您可以
在此处获取更多信息并提交简历。