10

It appears that std::span in C++20 is defined similarly to

template<class T>
class span
     {
     T* begin;
     size_t count;
     };

And not

template<class Iter>
class span
     {
     Iter begin;
     Iter end;
     };

which is more general (works with std::list, std::map, etc)?

Barry
  • 286,269
  • 29
  • 621
  • 977
user877329
  • 6,717
  • 8
  • 46
  • 88

1 Answers1

13

The whole point of std::span<T> is to be a view over contiguous data. pair<T*, size_> (or something like it) is the right way to represent that view. You cannot have a std::span that is a view over a std::list or a std::map, so it doesn't make sense to come up with a way to represent it. The point is to be a common, vocabulary type to just accept contiguous data.

It's also very important span is effectively type-erased. A span<int> could refer into a int[20] or a vector<int> or a int[] that is dynamically allocated somewhere or a llvm::SmallVector<int> or a ... It doesn't matter where it comes from, you just have the one type that is: "view over some contiguous ints".

It is true that pair<Iter, Iter> (or, more generally, pair<Iter, Sentinel>) is a more general representation that would work for more containers. There is such a thing in C++20 as well, it's called std::ranges::subrange<I, S>. But note here that we don't have the type-erasure aspect... a subrange over a map<K, V> will have a different type than a subrange over a different container with the same value_type, like list<pair<K const, V>> or vector<pair<K const, V>> or multimap<K, V>.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • But you could then use subrange everywhere you would otherwise use a span. Is the reason for different types then that you can provide a more optimal implementation if you use a separate class for the simple case? – user877329 Jun 28 '19 at 18:23
  • @user877329 It's not a question of "optimal"... `subrange` is basically equivalent to `span` in terms of representation. But they have different usability. `vector` is definitely convertible to `span`, but not necessarily to `subrange`. Also the template parameters have different meaning, `T` vs `T*`. `span` is just the more specific thing for the more specific use-case. – Barry Jun 28 '19 at 18:45
  • 2
    @user877329: "*But you could then use subrange everywhere you would otherwise use a span.*" No, you can't. You can pass a `span`'s data to a C API; you can't do that with an arbitrary iterator subrange. – Nicol Bolas Jun 28 '19 at 20:56
  • @Barry `subrange range{vec.data(), vec.data() + size()};`, if subrange ctor accepts the two iterators. – user877329 Jun 29 '19 at 10:28
  • @NicolBolas I should be able to do so if `Iter` is a pointer. Also, even if I could pass it to a C API, there has to exist such API, and most C API:s use a pointer and a size, and not a span struct so C compatibility is not a huge deal unless you rewrite POSIX or Windows API, and a bunch of other C libraries, which you don't. Sure, it could happen that calling `foo(T*, size_t)` looks exactly the same in assembly as `foo(std::span)`, but force a different function signature is definitely UB. – user877329 Jun 29 '19 at 10:39
  • @user877329 That's not the same thing as convertible. And Nicol said the span's data, not the span itself. – Barry Jun 29 '19 at 13:19
  • @user877329: "*there has to exist such API, and most C API:s use a pointer and a size, and not a span*" The point *isn't* that you can literally pass `std::span` to a C API. It's that, if your function takes a `span`, you can pass the guts of that `span` to a C API. You can't do that with an iterator-based one, not unless you force the iterator type to be a pointer. And even then, you don't get all of the useful features of `span`, such as implicit conversions from contiguous ranges. – Nicol Bolas Jun 29 '19 at 13:27
  • @Nicol Bolas "you don't get all of the useful features of span, such as implicit conversions from contiguous ranges." Aha, so the additional type *is* to enable more convenience features, that would have never worked (or wouldn't work well) on other iterators. – user877329 Jun 29 '19 at 15:23