O ponteiro é aritmético no armazenamento alocado permitido desde C ++ 20?

10

No padrão C ++ 20, diz-se que os tipos de matriz são do tipo vida útil implícita .

Isso significa que uma matriz para um tipo de duração não implícita pode ser criada implicitamente? A criação implícita de tal matriz não causaria a criação dos elementos da matriz?

Considere este caso:

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to object" (which object?)
std::string * sptr = std::launder(static_cast<std::string*>(ptr));
//pointer arithmetic on not created array elements well defined?
new (sptr+1) std::string("second element");

Esse código não é mais UB desde C ++ 20?


Talvez assim seja melhor?

//implicit creation of an array of std::string 
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to the array of 10 std::string" 
std::string (* sptr)[10] = std::launder(static_cast<std::string(*)[10]>(ptr));
//pointer arithmetic on an array is well defined
new (*sptr+1) std::string("second element");
Oliv
fonte
11
Acabei de pesquisar o padrão C ++ 20 (rascunho) e não encontrei nada que descreva matrizes como um "tipo de duração implícita" (e, sim, procurei por variações). Forneça uma descrição mais detalhada de sua reivindicação (por exemplo, seção e cláusula na norma). É um pouco difícil responder à sua pergunta sem conseguir encontrar a fonte, sem falar em qualquer contexto relevante.
Peter
11
@Peter: eel.is/c++draft/basic.types#9 , última frase
geza
Eu estava olhando o PDF open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf (ostensivamente o último rascunho de trabalho) e ele nem sequer tem essa frase. Parece que você precisará encontrar o significado de "vida implícita" também. Suspeito que seu link tenha recebido algumas "edições em andamento" que nem chegaram aos rascunhos de trabalho liberados.
Peter
11
@ Peter As alterações são o resultado da fusão do P0593 com o padrão da recente reunião de Praga. Ainda não divulgaram o rascunho resultante, mas você pode ver o texto mesclado neste commit .
noz

Respostas:

3

Isso significa que uma matriz para um tipo de duração não implícita pode ser criada implicitamente?

Sim.

A criação implícita de tal matriz não causaria a criação dos elementos da matriz?

Sim.

É isso que torna std::vectorimplementável em C ++ comum.

TC
fonte
Você poderia confirmar também que std::launder(static_cast<std::string*>(ptr))não retorna um ponteiro para o primeiro elemento da matriz porque não está dentro de sua vida útil, mas que std::launder(static_cast<std::string(*)[10]>(ptr))retorna um ponteiro para a matriz, porque a matriz está dentro de sua vida útil?
Oliv
Isso parece correto para mim.
TC
@ Oliv E suponho que std::laundernão seja realmente necessário, porque o eel.is/c++draft/intro.object#11 garante que ptrjá apontará para o array?
walnut
@ Walnut, eu senti falta disso. Portanto, um static_casta std::string (*) [10]deve ser suficiente! tx.
Oliv
@ Oliv Mas acho que a pergunta então é se o seu primeiro exemplo sem o std::launderserá bem definido. Não há nenhum std::stringobjeto para o qual apontar, mas ptrpoderia apontar para a matriz, para que a conversão estática deixe o valor inalterado e sptrtambém aponte para a matriz. Com std::launderele é o UB simplesmente por causa dos std::launderrequisitos.
walnut