It is possible to construct a std::span from a std::vector (as the prototype for a contiguous container), both via the range constructor and an explicit pair of iterators:
#include <span>
#include <vector>
std::vector<int> owning;
std::span<int> view1{owning.begin(), owning.end()}; // works
std::span<int> view2{owning}; // works
But when doing the same with a small_vector from Boost's container library, which should be contiguous, too, I am running into issues (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)
The problem seems to be that the iterators of boost::small_vector don't satisfy the std::contiguous_iterator concept, i.e. this fails with both gcc and clang, libc++ and libstdcxx (godbolt):
static_assert(
std::contiguous_iterator<boost::container::small_vector<int, 10>::iterator>);
The storage of small_vector might be in-place or on the heap, but always contiguous. So what's the issue here?
std::contiguous_iteratorhas specific requirements in C++20 which were not part of any pre-C++20 interface. Since those interfaces did not exist pre-C++20 (particularly thecontiguous_iterator_tag), they couldn't be used bysmall_vector<T>::iterator.Of course one can add such an interface, conditioned on the existence of C++20 features. But code written before the C++20 came about simply won't be able to be a
contiguous_iteratorwithout work to update it. While there was a C++17 "ContiguousIterator" requirement, it had no tag or other way to detect whether an iterator was contiguous. C++20 added such a tag (and other stuff) when it added a proper concept.