2010-01-25 18 views
17

So che sizeof è un calcolo in fase di compilazione, ma questo mi sembra strano: il compilatore può prendere un nome di tipo o un'espressione (da cui deduce il tipo). Ma come si identifica un tipo all'interno di una classe? Sembra che l'unico modo sia di passare un'espressione, che sembra piuttosto goffo.Perché non taglia i membri di struct parse?

struct X { int x; }; 
int main() { 
    // return sizeof(X::x); // doesn't work 
    return sizeof(X()::x); // works, and requires X to be default-constructible 
} 
+11

supporto per 'sizeof (X :: x)' è incluso in C++ 0x (cfr http://www.open -std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html). –

+0

@James +1 al tuo commento. La mia risposta (cancellata) avrebbe dovuto essere un commento in realtà, perché Tom non menzionava C++ 0x. Forse lo vuole in C++ 98 :) – AraK

+0

Sì, la mia domanda riguarda C++ 98. Tuttavia, anche se costruisco con '-std = C++ 0x', non funziona (GCC 4.3.2). Esistono implementazioni di compilatori che lo supportano ancora? – Tom

risposta

27

Un metodo alternativo funziona senza bisogno di un costruttore di default:

return sizeof(((X *)0)->x); 

Puoi avvolgere questo in una macro in modo che legge meglio:

#define member_sizeof(T,F) sizeof(((T *)0)->F) 
+0

AFAIK, il dereferenziamento di un puntatore NULL è un comportamento non definito. Questa regola si applica anche in questo caso? – AraK

+5

@AraK: Non penso: "L'operando [di sizeof] è un'espressione, * che non viene valutata *, o un tipo-id tra parentesi" (5.3.3/1; emphasis mine). –

+2

Il puntatore NULL non viene mai dereferenziato. Questa è un'operazione in fase di compilazione. È solo per fare in modo che il compilatore faccia The Right Thing (tm). –

0

Che dire offsetof? Dai un'occhiata allo here. Guarda anche here, che combina sia sizeof e offsetof in una macro.

Spero che questo aiuti.

+0

Non aiuta, perché il compilatore (mentre è richiesto per ordinare gli elementi della struttura nell'ordine dichiarato) è libero di riempirli come ritiene necessario. – dmckee

+0

dmckee: Oh, Ok..grazie per il tuo contributo! Saluti :) – t0mm13b

10

Ecco una soluzione senza il puntatore nullo brutto dereferenziazione;)

struct X { int x; }; 

template<class T> T make(); // note it's only a declaration 

int main() 
{ 
    std::cout << sizeof(make<X>().x) << std::endl; 
} 
+0

oh, questo è trixy! – Tom

+1

Non potresti semplicemente dire "extern T fakeT; sizeof (fakeT.x); '? – MSalters

Problemi correlati