Boost 的 small_vector 的迭代器类型不应该满足 std::contiguous_iterator 概念吗?

问题描述

可以通过范围构造函数和显式的迭代器对从 std::span(作为连续容器的原型)构造 std::vector

#include <span>
#include <vector>

std::vector<int> owning;
std::span<int> view1{owning.begin(),owning.end()}; // works
std::span<int> view2{owning}; // works

但是,当对 Boost 容器库中的 small_vector(也应该是连续的)执行相同操作时,我遇到了问题 (godbolt):

#include <span>
#include <boost/container/small_vector.hpp>

boost::container::small_vector<int,10> owning;
std::span<int> view1{owning.begin(),owning.end()}; // Error
std::span<int> view2{owning}; // Error (works with clang + libc++ though)

问题似乎是 boost::small_vector 的迭代器不满足 std::contiguous_iterator 概念,即 gccclang 都失败了,{{1} } 和 libc++ (godbolt):

libstdcxx

static_assert( std::contiguous_iterator<boost::container::small_vector<int,10>::iterator>); 的存储可能就地或在堆上,但始终是连续的。那么这里的问题是什么?

解决方法

std::contiguous_iterator 在 C++20 中有 specific requirements,它不是任何 C++20 之前的接口的一部分。由于这些接口在 C++20 之前不存在(尤其是 contiguous_iterator_tag),因此 small_vector<T>::iterator 无法使用它们。

当然可以添加这样的接口,条件是C++20特性的存在。但是在 C++20 出现之前编写的代码如果不进行更新就无法成为 contiguous_iterator。虽然有 C++17 的“连续迭代器”要求,但它没有标签或其他方式来检测迭代器是否连续。 C++20 在添加了适当的概念时添加了这样一个标签(和其他东西)。