Um colega de trabalho queria escrever isso:
std::string_view strip_whitespace(std::string_view sv);
std::string line = "hello ";
line = strip_whitespace(line);
Eu disse que o retorno string_view
me deixava desconfortável a priori e, além disso, o apelido aqui parecia UB para mim.
Posso dizer com certeza que line = strip_whitespace(line)
, neste caso, é equivalente a line = std::string_view(line.data(), 5)
. Eu acredito que irá chamar string::operator=(const T&) [with T=string_view]
, que é definido para ser equivalente a line.assign(const T&) [with T=string_view]
, que é definido para ser equivalente a line.assign(line.data(), 5)
, que é definido para fazer isso:
Preconditions: [s, s + n) is a valid range.
Effects: Replaces the string controlled by *this with a copy of the range [s, s + n).
Returns: *this.
Mas isso não diz o que acontece quando existe um alias.
Ontem fiz esta pergunta no Slack cpplang e recebi respostas contraditórias. Procurando respostas super autoritativas aqui e / ou análise empírica das implementações de fornecedores de bibliotecas reais.
Eu escrevi casos de teste para string::assign
, vector::assign
, deque::assign
, list::assign
, e forward_list::assign
.
- O Libc ++ faz com que todos esses casos de teste funcionem.
- O Libstdc ++ faz com que todos funcionem, com exceção de
forward_list
, que segfaults. - Não conheço a biblioteca da MSVC.
O segfault no libstdc ++ me dá esperança de que este seja UB; mas também vejo o libc ++ e o libstdc ++ fazendo um grande esforço para fazer esse trabalho pelo menos nos casos mais comuns.
*this
. Mas não vejo nada para impedir a reutilização do armazenamento existente; nesse caso, isso se torna não especificado, uma vez que a semântica da substituição do armazenamento não é especificada.
assign
requisitos em [tab: container.seq.req] .