Eu defini a seguinte função:
template<
std::ranges::contiguous_range R,
typename T = std::ranges::range_value_t<R>
>
std::span<T> foo(R&& r, const T& someValue) {
std::span<T> sp{r.begin(), r.end()};
/// ...
return sp;
}
Agora tenho três casos de uso:
std::vector<std::string> baseVec;
auto a = foo(baseVec, {""});
std::span<std::string> sp{baseVec};
auto b = foo(sp, {""});
const std::vector<std::string>& ref = baseVec;
auto c = foo(ref, {""}); // <------------------ problem here!
Pelo que entendi, foo(ref)
não será possível compilar porque o span
interior criado foo
é do tipo span<T>
, enquanto neste caso deveria ser span<const T>
.
Então, como posso escrever foo
de forma que aceite todos os três casos?
A questão é que o valor
value_type
de um intervalo nunca éconst
qualificado. Masreference
o tipo de intervalo poderia ser - embora isso ainda esteja errado porque seriastring const&
.Os iteradores contíguos são obrigados a ter seu tipo de referência for
U&
some typeU
, portanto, se simplesmente descartarmos a referência final, obteremos um tipo potencialmente qualificado para const:Observe que você não precisa passar
r.begin()
er.end()
intospan
,span
possui um construtor de intervalo.No entanto, isso ainda não está correto porque o original também estava errado.
contiguous
é um critério insuficiente aqui, também precisamos que o intervalo sejasized
para que possamos construir um valorspan
a partir dele:Além disso, você provavelmente não deseja deduzir
T
do argumento - você realmente deseja que seja especificamente o corretoT
associado ao intervalo:Observe que alterei seu código para construir
span
usando parênteses em vez de colchetes. Isso ocorre porque passar um par de iteradores para um inicializador usando chaves não é uma boa ideia, porque poderia facilmente fazer a coisa errada. Considerar:E o mesmo vale para
span
, que terá uminitializer_list
construtor começando em C++26.Você pode seguir o caminho proverbial. Se o compilador for tão inteligente, deixe-o descobrir o tipo sozinho. Com a dedução de argumentos do modelo de classe, é possível.