Utilisation de std :: launder pour “valider” la valeur du pointeur non “pointeur vers object” depuis C ++ 17

Selon cette réponse , depuis C ++ 17, même si un pointeur a la bonne adresse et que le bon type de déréférencement peut provoquer un comportement indéfini .

alignas(int) unsigned char buffer[2*sizeof(int)]; auto p1=new(buffer) int{}; auto p2=new(p1+1) int{}; *(p1+1)=10; // UB since c++17 

La raison en est que la valeur du pointeur de p1+1 est un pointeur situé au-delà de la fin d’ un object. Cet exemple peut-il être ramené à un comportement défini à l’aide de std::launder :

  *std::launder(p1+1)=10; // still UB? 

Deuxièmement, serait-il également utile dans le cas suivant?

 alignas(int) unsigned char buffer[3*sizeof(int)]; auto pi = new (buffer) int{}; auto pc = reinterpret_cast(pi);//not a "pointer to" an element of buffer //since buffer[0] and *pc //are not pointer interconvertible //pc+2*sizeof(int) would be UB auto pc_valid = std::launder(pc) //pc_valid is a pointer to an element of buffer auto pc_valid2 = pc_valid+2*sizeof(int); //not UB thanks to std::launder auto pi2 = new (pc_valid2) int{}; 

Les octets constituant l’object int p2 ne sont pas accessibles via p1+1 .


La règle “accessible” signifie essentiellement que launder ne vous permet pas d’accéder à un stockage auquel vous ne pouvez pas accéder légalement via le pointeur d’origine. Puisqu’une fonction opaque peut launder pointeurs autant qu’elle le souhaite, autoriser ce type de manigances empêcherait considérablement l’parsing par évasion.