gsl::span<T> and gsl::span<const T> overloads are ambigous

Viewed 2710

C++ Core Guidelines promotes the practice of using span.

The problem is with const and mutable ranges. This is what I tried to do:

auto foo(gsl::span<int>);         // 1st
auto foo(gsl::span<const int>);   // 2nd

But they can't be called without explicit span cast/construct of the argument:

std::vector<int> v;
const std::vector<int> cv;
const std::vector<int>& crv = v;

// ambiguous
// want to call 1st
foo(v);

// ambiguous, although 1st is illegal (static_assert kicks in)
// want to call 2nd
foo(cv); // ambiguous
foo(crv); // ambiguous

What is the proper way to deal with this?

This seems like something that should be trivial, analog to const T& and T& overloads, yet it isn't (or I just don't see it).

Just to be on the same page, foo(gsl::span<int>{v}) is cumbersome, and I want to avoid it, leave the callers simple: foo(v).


I generalized the issue, but just in case this is an XY problem, this is what I actually try to do:

auto split(gsl::cstring_span<> str) -> std::vector<gsl::cstring_span<>>;
auto split(gsl::string_span<> str) -> std::vector<gsl::string_span<>>;

and want to be callable with [const] char *, [const] string, etc. arguments.

2 Answers
Related