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 span
s 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