C++23 容器推导指引中对于分配器的非推导语境(P1518R2)


在C++23中,P1518R2提案对容器推导指引(CTAD)中的分配器处理方式进行了重要的改进。这一改进主要解决了在容器推导过程中分配器参数可能导致的推导失败或错误推导的问题。

背景:容器推导指引与分配器问题

容器推导指引(CTAD)是C++17引入的一项特性,它允许编译器根据构造函数的参数自动推导模板参数,从而简化了容器的实例化过程。然而,在处理分配器时,CTAD存在一些问题,主要体现在以下两个方面:

  1. 分配器类型不满足条件时推导失败:在某些情况下,即使提供了有效的分配器类型,推导指引也可能因为分配器类型不满足特定条件而失败。
  2. 分配器参数导致冲突推导:当分配器参数与容器的其他参数一起参与推导时,可能会导致模板参数的冲突。

问题示例

1. 分配器类型不满足条件时推导失败

以下是一个典型的例子:

#include <memory_resource>
#include <stack>

int main() {
    std::pmr::monotonic_buffer_resource mr;
    std::pmr::polymorphic_allocator<int> a = &mr;
    std::pmr::vector<int> pv(a);

    auto noCtadStack = std::stack<int, std::pmr::vector<int>>(pv, &mr); // 正常工作
    auto ctadStack = std::stack(pv, &mr);  // 推导失败
}

在上述代码中,std::stack的推导指引无法正确处理&mr,因为std::pmr::monotonic_buffer_resource没有value_type嵌套类型,因此不被视为分配器。

2. 分配器参数导致冲突推导

另一个问题是分配器参数可能导致模板参数的冲突。例如:

#include <memory_resource>
#include <vector>

int main() {
    std::pmr::monotonic_buffer_resource mr;
    std::pmr::polymorphic_allocator<int> a = &mr;
    std::pmr::vector<int> pv(a);

    auto noCtadVector = std::vector<int, std::pmr::polymorphic_allocator<int>>(pv, &mr); // 正常工作
    auto ctadVector = std::vector(pv, &mr); // 推导失败
}

在这个例子中,std::vector的构造函数参数pv&mr分别推导出不同的Allocator类型,导致推导失败。

P1518R2 的解决方案

P1518R2 提案通过以下方式解决了上述问题:

  1. 修改容器适配器的推导指引规则:对于容器适配器(如std::stack),如果推导指引具有Container模板参数,则不再因Allocator参数不满足条件而排除该推导指引。
  2. 引入非推导上下文:对于标准容器的构造函数,使用std::type_identity_t将分配器参数标记为非推导上下文。例如,std::vector的构造函数签名从:
    constexpr vector(const vector&, const Allocator&);
    
    改为:
    constexpr vector(const vector&, const type_identity_t<Allocator>&);
    

这种改动确保分配器参数不会干扰模板参数的推导。

总结

P1518R2 提案通过引入非推导上下文和修改推导指引规则,显著改善了C++23中容器推导指引对分配器的处理。这些改进使得代码更加简洁,同时避免了因分配器类型导致的推导失败。随着C++23的逐步普及,这些改进将为开发者带来更流畅的开发体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码事漫谈

感谢支持,私信“已赏”有惊喜!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值