Closed beinhaerter closed 1 year ago
This appears to be expected behavior.
If you replace gsl::span
with std::span
in your example, the behavior is actually undefined:
#include <array>
#include <span>
void f() {
std::array<char, 20> a{};
gsl::span<char> s1{a};
gsl::span<char, 10> s2{s1.first(10)};
gsl::span<char, 10> s3{s1}; // undefined behavior
}
This is because when constructing a std::span
of static extent from a std::span
of dynamic extent
The behavior is undefined if both extent != dynamic_extent and source.size() != extent are true.
(https://en.cppreference.com/w/cpp/container/span/span)
When running that code with MSVC in debug mode, you actually get a runtime error "Cannot construct span with static extent from other span as other.size() != extent"
.
So this is a feature (defect?) of the std::span
constructors.
... but ... since the behavior is technically "undefined" by std::span
why can't we choose to implement it in a more convenient manner for gsl::span
?
I imagine the choice to disallow it was made to keep the behavior consistent with how static-extent spans behave:
gsl::span<char, 20> s1{ a };
gsl::span<char, 19> x{ s1 }; // compile-time error, can't find appropriate constructor
std::span<char, 20> s2{ a };
std::span<char, 19> y{ s2 }; // compile-time error, can't find appropriate constructor
So, considering that fundamentally the design of gsl::span
is such that it should match the interface of std::span
exactly, while offering bounds checking, gsl::span
raises the error you reported.
Initializing s2 succeeds, but initializing s3 fails. Is this expected behaviour or a bug? At least for me it is surprising that I need to pass a dynamic extent span with exactly the same extent.
This
Expects
is causing the abort: