I tried a little example to get used to the GSL and range-v3 libraries and I wondered how they could work together. I have this toy example
#include <iostream>
#include <range/v3/all.hpp>
using namespace std;
using namespace ranges;
void example_vector(vector<int> const& v)
{
  ranges::for_each(view::tail(v), [](int x){
    cout << x << ' ';
  });
  cout << '\n';
}
int main()
{
   auto seq = vector<int> { 2,2,2,0,0,2,1,2 };
   example_vector(seq);
}
which works. But if I try to use gsl::span<int> as a range it leads to an error message. The compiler tells me that span does not fullfill the view concept.
#include <gsl.h>
// ...
void example_span(gsl::span<const int> v)
{
  ranges::for_each(view::tail(v), [](int x){
    cout << x << ' ';
  });
  cout << '\n';
}
Compiler message:
note: candidate template ignored: disabled by 'enable_if'
      [with Rng = gsl::span<const int, -1> &, Rest = <>, _concept_requires_123 = 42]
                    CONCEPT_REQUIRES_(ViewConcept<Rng, Rest...>())>
But in my understanding it should since a span is a particular view and even has begin() and end() iterators (of the same type).
span currently needs some adaption if I would like to
use both libraries together in some piece of (non-industrial) software. What
should I change to make these work together? (if it is a good idea at all)range-v3?" Is inheritance from facades,
adaptors or such the only way to tell the compiler currently about these conceptional requirements?Range v3 is a generic library that augments the existing standard library with facilities for working with ranges. A range can be loosely thought of a pair of iterators, although they need not be implemented that way.
gsl::span is a replacement for (pointer, length) pairs to refer to a sequence of contiguous objects. It can be thought of as a pointer to an array, but that knows its bounds. For example, a span<int,7> refers to a sequence of seven contiguous integers.
The library used in the code examples is not really the C++20 ranges, it's the ranges-v3 open-source library from Eric Niebler, which is the basis of the proposal to add ranges to the C++. It's a header-only library compatible with C++11/14/17.
The View concept in range-v3 (and the ranges TS, for that matter) requires a type R to satisfy both the Range concept -- begin(r) and end(r) delimit an iterator range -- and the Semiregular concept -- R must be copy/move constructible copy/move assignable, and default constructible. The iterator and sentinel types of a Range (what begin and end return) must also be Semiregular (amongst other requirements).
The span family doesn't satisfy the View concept since spans are not default constructible in some cases, and their iterators are not default constructible in any cases. Since even Standard C++ requires default construction for Forward iterators, the current span iterators conform to neither the Ranges TS, range-v3, nor Standard C++.
That said, the changes necessary to meet all these families of requirements are minimal and straight-forward.
range-v3 now contains an implementation of span that does properly model the View/Range concepts.
gsl::span now has default constructible iterators. Consequently, spans are now usable with range-v3. Spans with dynamic extent (e.g., gsl::span<int>) model the Range & View concepts, spans with static extent (e.g., gsl::span<int, 42>) model only Range since they do not meet View's requirement for default construction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With