上一次 ,我们使用SFINAE来确定类型是否具有定义,并将其与
if constexpr
和泛型lambda表达式结合使用,以便代码可以使用该类型(如果已定义),同时仍被编译器接受(并且丢弃)(如果未定义类型)。
但是,此应用程序存在一些问题:
- 每次您需要编写一个
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
需要使用外部括号,而
卷积表达式需要
使用内部括号。 卷积表达式扩展为
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提交申请。