Tenho uma construção semelhante ao CRTP:
class Derived : public Base<Derived>
Preciso calcular um ponteiro para um Derived
objeto a partir de um ponteiro para Base<Derived>
objeto via reinterpret_cast
. Não posso usar dynamic_cast
porque não estou usando funções virtuais aqui.
Os tipos são fornecidos, eu tenho o ponteiro para o Base<Derived>
objeto. Preciso do deslocamento de bytes entre os dois tipos, para poder usar reinterpret_cast
. Como faço isso (sem comportamento indefinido)? É possível fazer em tempo de compilação / salvar como uma static constexpr
variável (estou usando C++20)?
Não há necessidade de cálculos de deslocamento ou
reinterpret_cast
.Se você tiver certeza de que o objeto é realmente
Derived
um, você pode simplesmente usarstatic_cast
:Observe que se
pBase
o comando acima não apontar realmente para umDerived
objeto, usarstatic_cast
na última linha invocará undefined-behavior (UB) .Uma observação lateral:
como @BenVoigt comentou abaixo , é comum adicionar um método auxiliar à classe base do CRTP que faz exatamente essa conversão.
Ou seja, adicione algo como isto
Base<Derived>
(substituaDerived
se necessário pelo nome do parâmetro de modelo real emBase
):O padrão CRTP depende de um static_cast<> entre a classe base e o tipo derivado. O tipo de classe Derived é a única classe derivada do tipo de modelo Base instanciado. Portanto, é garantido que a
static_cast<Derived*>(this)
é seguro dentro da classe de modelo Base. É por isso que é comum ver código como:Aqui,
class obj
só é necessário implementar a API da classe basevalue()
para que a base intermediáriaclass Inc
implemente operadores de pré e pós incremento para ela.(@wohlstad obteve a primeira resposta, então pensei em preencher uma resposta um pouco mais detalhada)