如何让自定义类兼容接收range参数的std::span构造函数
问题描述
我希望可以将自定义容器传入这个std::span构造函数:
template< class R > explicit(extent != std::dynamic_extent) constexpr span( R&& range );
我需要为自定义类添加哪些内容,才能使其满足传入接收range参数的std::span构造函数的要求?
例如,我们可以对std::vector执行如下操作:
std::vector<int> v = {1, 2, 3}; auto span = std::span{v};
我已经为自定义类添加了以下实现:
Type* begin() { return m_Data; } Type* end() { return m_Data + m_Length; } const Type* data() const { return m_Data; } size_t size() const { return m_Length; }
上述实现已经支持范围for循环、std::data(my_container)以及std::size(my_container)调用。我还缺少哪些实现才能将自定义容器传入std::span构造函数?是否需要实现更复杂的迭代器?
解答
你不需要实现复杂的自定义迭代器,现有实现已经非常接近要求,只需要补全几个小细节即可:
- 补充const版本的
begin()和end()方法
你当前只有非const版本的迭代器方法,会导致const修饰的自定义容器实例无法匹配std::span<const T>的构造要求,补充后代码如下:
const Type* begin() const { return m_Data; } const Type* end() const { return m_Data + m_Length; }
- 可选补充非const版本的
data()方法
虽然不是强制要求,但补充非const的data()可以避免部分重载匹配场景下的歧义,提升兼容性:
Type* data() { return m_Data; }
原理说明
std::span的range构造函数对传入的范围有以下核心约束,你的实现已经覆盖了大部分:
- 是连续范围:你直接返回原生指针作为迭代器,原生指针天然满足连续迭代器的要求,且你的容器元素本身就是连续存储的,符合
std::ranges::contiguous_range的要求 - 支持
std::ranges::data()和std::ranges::size()获取起始指针和长度:你已有的data()和size()方法已经满足这个要求 - 排除了span、std::array、原生数组等特殊类型:自定义容器不受这个约束影响
补全上述const迭代器方法后,你就可以正常将自定义容器传入std::span的range构造函数,无论是可变还是const的容器实例都可以正常匹配。
内容的提问来源于stack exchange,提问作者Erunehtar
相关产品推荐
相关产品推荐

