Existe uma maneira de retornar a range::view
em um std::expected
constructo? Por exemplo, no pseudocódigo abaixo, o que posso escrever em vez de rangeType
?
std::expected<rangeType, error> get_range()
{
if (some_condition(x))
return std::unexpected(errorcode);
return data|ranges::views::take(x);
}
Até onde posso ver, não há uma boa solução para esse problema.
O melhor que posso fazer é usar
auto
o tipo de retorno. Para isso, você precisa alterar a função para retornar o mesmo tipo em todos os caminhos. Você faz isso obtendo o tipo da visualização comdecltype
e explicitamente usa ostd::expected
tipo no retorno. Para o valor inesperado, eu uso astd::expected
sobrecarga do construtor com astd::unexpected_t
tag .Isso colocará o tipo de visualização de intervalo no protótipo da função. Isso significa que modificar a implementação em como você constrói
r
ou alterar odata
tipo alterará o protótipo da função. (porque cada visualização tem um tipo distinto). Isso pode ser um problema ou não, dependendo do seu caso de uso da função.As visualizações são preguiçosas, então construir
r
antes de verificar sua condição não deve ser um problema. No entanto, se for ou se você quiser evitar isso, você pode obter o tipo der
comstd::declval
, mas é trabalhoso e quebradiço.Ao retornar a
std::expected<DifficultTypeToSpell, E>
de uma função, pode-se evitar soletrar o tipo completamente, usando a interface monádica destd::expected
. Comece com astd::expected<T, E>
que contém o erro real, ou alguma construção padrãoT
(que poderia até servoid
), etransform
com a expressão que realmente fornece o tipo que é difícil de soletrar.Então o código poderia ser algo como isto:
O tipo de intervalo é complicado, o mais curto que você pode fazer é inferir o tipo a partir do uso usando decltype e declval .
por exemplo
o tipo de
r
é muito complicado de escrever, além disso, se você tentar retorná-lo da função, o intervalo pode ficar oscilando, e você só pode retornar 1 tipo de intervalo, então não pode aplicar condicionalmente transformações diferentes.a melhor alternativa é passar um functor como o que std::for_each faz e aplicá-lo ao intervalo, dessa forma você não corre o risco de usar um intervalo pendente, caso contrário, pode ser mais seguro retornar a
std::vector
e encarar a situação, talvez usarpmr::vector
para reduzir a sobrecarga de alocações.Prefiro usar tipos de retorno finais quando o tipo de retorno fica complicado.
Poderia ficar assim e o resto da sua função permaneceria inalterado: