如何实现类iota的C++23 constant_range工厂(值类型解引用)
如何正确实现返回自定义类型左值引用的constant_range视图?
我实现了一个类似iota_view的范围工厂,用于生成自定义类型MyType的实例,核心代码如下:
struct MyType; struct MyIterator { using value_type = MyType; using iterator_concept = std::input_iterator_tag; // ... 其他迭代器接口实现 auto operator*() const -> MyType; }; struct MyView : public std::ranges::view_interface<MyView> { auto begin() const -> MyIterator; auto end() const -> MyIterator; };
我尽可能遵循iota_view的设计,但测试发现MyView并不满足constant_range要求:
static_assert( std::ranges::constant_range<std::ranges::iota_view<int>>); static_assert(!std::ranges::constant_range<MyView>); // 不满足constant_range!
问题根源
经排查,问题出在MyIterator不是constant-iterator:
std::same_as<std::iter_const_reference_t<MyIterator>, std::iter_reference_t<MyIterator>>不成立std::iter_reference_t<MyIterator>是MyType,而std::iter_const_reference_t<MyIterator>是const MyType
如果把MyType替换为内置类型int(和iota_view的情况一致),则二者均为非const类型。进一步分析发现,std::iter_const_reference_t基于std::common_reference_t实现,而该类型对内置类型和自定义类型的处理存在差异:
- 当
T为int时,decltype(false? val<const T&&>() : val<T>())的结果是int - 当
T为MyType时,结果是const MyType
尝试的解决方法
我通过特化std::basic_common_reference解决了当前问题:
template<template<class> class TQual, template<class> class UQual> struct std::basic_common_reference<MyType, MyType, TQual, UQual> { using type = std::common_type_t<TQual<MyType>, UQual<MyType>>; };
但不确定这种做法是否符合C++标准,而且如果视图是模板类,其是否为constant_range会依赖模板参数是否有对应的特化,这显然不合理。
请问:如何正确实现返回左值引用类型的constant_view?
内容的提问来源于stack exchange,提问作者Drag-On
相关产品推荐
相关产品推荐

