c++26新功能—ADL的证明

一、介绍

之前在模板相关的技术中对ADL(Argument Dependent Lookup,参数依赖查找)进行过分析和举例说明。但在实际的应用中,如果迭代器是危险的指针类型时,其不会进行ADL的动作。但如果其类似于模板projected<Danger*, identity>这种类型时,ADL的操作就会进行。但对于Ranges库来说,由于其缺乏ADL的防护性,在某些情况下就会导致异常。所以在C++26中重新规范了
projected<I, Proj>,从而修复了这个问题即其相关联实体不再包含其模板参数。
不过一般情况下,原生指针的大多数操作都不会触发ADL的行为。比如下面的情况:

Holder<Incomplete> *a[10] = {}; // ten null pointers
Holder<Incomplete> **p = a;                 // OK
p += 1;                                     // OK
assert(*p == nullptr);                      // OK
assert(p == a+1);                           // OK
assert(std::count(a, a+10, nullptr) == 10); // OK

二、C++20中的问题和解决方式

看一下C++20中的Ranges中的例子:

template<class T> struct Holder { T t; };
struct Incomplete;

Holder<Incomplete> *a[10] = {}; // 十个空指针
assert(std::count(a, a+10, nullptr) == 10); // 正常
assert(std::ranges::count(a, a+10, nullptr) == 10); // 硬错误

这段代码出错误的原因就在于indirectly_comparable<T*, T*, Pred>中利用到了projected<T*, identity>的所有关联类型,而T中包含Holder。
针对上面的问题,在C++26中提出了下面的解决方式就是引入ADL防护即不再让T成为相关的关联类型。也就是ADL-proof std::projected。

template<class Associated>
struct projected { };
//将上面的projected替换为下面的:
template<class T>
struct __projected_impl {
  struct type { };
};

template<class NonAssociated>
using projected = __projected_impl<NonAssociated>::type;

ADL会关联派生类的基类,但不会关联嵌套类的包含类即__projected_impl::type中的::充当了防止不需要的 ADL的防火墙。

三、另外一种技术实现

另外,在一些提案中有“phrase of power”这种技术,如果这种技术能够应用,也可能使用这种技术来替代相关的projected的实现。其实就是在类模板的模板头增加一些特定的标记,arguments are not associated entities即参数不是关联实现。假如可以使用这种技术,则相关的应用就可以使用下面的方式:

using T = Holder<Incomplete>*;

static_assert(std::equality_comparable<T>); // 正常
static_assert(std::indirectly_comparable<T*, T*, std::equal_to<>>); // 将会正常
static_assert(std::sortable<T*>); // 将会正常

int main() {
  Holder<Incomplete> *a[10] = {}; // 十个空指针
  assert(std::count(a, a+10, nullptr) == 10); // 正常
  assert(std::ranges::count(a, a+10, nullptr) == 10); // 将会正常
}

四、总结

从这些细节来看,一如以前的标准,C++26中也对原来遗留下来的技术债在不断的偿还。既有功能的完善和新的技术的解决方式,这些都是保障C++不断向前发展的一个重要推动力量。我们的学习,应该也和标准的演进保持一致。查漏补缺,不断向上。

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值