Sto provando a scrivere una struttura per calcolare l'offset del puntatore tra una base e una classe derivata come espressione costante in C++ 03. Il codice è il seguente:Perché il typecasting di un intero letterale a un valore del puntatore produce un'espressione non const?
template <typename Base, typename Derived, typename Via = Derived>
struct OffsetToBase
{
static const std::ptrdiff_t val =
(const char*const)static_cast<Base*const>(static_cast<Via*const>((Derived*const)(1u << 7))) -
(const char*const)(1u << 7);
};
Il codice viene compilato in GCC, ma non in clang e VC. L'errore prodotto da clang e VC in sostanza dice che l'inizializzatore non è un'espressione costante con clang che sottolinea ulteriormente la sottoespressione (Derived*const)(1u << 7)
.
Quindi, la mia domanda è che cosa dicono gli standard di questo? E se l'inizializzatore non si qualifica come un'espressione costante secondo gli standard, allora qual è il ragionamento alla base di questo?
UPDATE: per il vostro interesse, ho trovato questi due dibattiti:
"Initializer element is not constant" error for no reason in Linux GCC, compiling C
About cast in integer constant expression (in standard C)
Ma non credo che le stesse regole si applicano a C++.
Ho paura che questo è UB: stai dereferenziazione un puntatore nullo –
Naturalmente 'static_cast' lavora su puntatori. Esegui la sottrazione _after_ la conversione in numero intero. – Oktalist
Grazie per la citazione dallo standard.Tuttavia, non sembra che risolva il vero problema, dato che il seguente codice (che gira in 'const std :: ptrdiff_t' invece di' const char * const') non esegue il compilatore su clang e VC: 'template struct OffsetToBase { static const std :: ptrdiff_t val = (const std :: ptrdiff_t) static_cast (static_cast ((Derived * const) (1U << 7))) - (const std :: ptrdiff_t) (1u << 7); }; ' –
Lingxi