tags:

views:

401

answers:

5

Is it possible to determine the size of a C++ class at compile-time?

I seem to remember a template meta-programming method, but I could be mistaken...


sorry for not being clearer - I want the size to be printed in the build output window

+6  A: 

Whats wrong with sizeof? This should work on objects and classes.

void foo( bar* b )
{
  int i = sizeof bar;
  int j = sizeof *b;

  // please remember, that not always i==j !!!
}

Edit:

This is the example I was thinking of, but for some reason it's not working. Can anyone tell me what's wrong?

#include <iostream>
using namespace std;
class bar {
public: int i;
        bar( int ii ) { i = ii; }
        virtual ~bar(){ i = 0; }
        virtual void d() = 0;
};

class bar2: public bar {
public: long long j;
        bar2( int ii, long long jj ):bar(ii){ j=jj; }
        ~bar2() { j = 0; }
        virtual void d() { cout <<  "virtual" << endl; };
};

void foo( bar *b )
{
        int i = sizeof (bar);
        int j = sizeof *b;
        cout << "Size of bar = " << i << endl;
        cout << "Size of *b  = " << j << endl;
        b->d();
}


int main( int arcc, char *argv[] )
{
        bar2 *b = new bar2( 100, 200 );
        foo( b );
        delete b;
        return 0;
}

The application been run on linux (gcc 4.4.2):

[elcuco@pinky ~/tmp] ./sizeof_test
Size of bar = 8
Size of *b  = 8
virtual
elcuco
@elcuco - the second line should be `sizeof(*b)`
R Samuel Klatchko
@R Samuel: Or just `sizeof *b`. `sizeof` is an operator not requiring brackets, except that type names have to be surrounded by brackets, similar to casting syntax.
Chris Jester-Young
When would i!=j? `sizeof` calculates at compile time, and all that's known is the type of the argument - in both cases this is `bar`. If you have a child class of `bar` that is larger, and you pass a pointer to an instance of the child into this function, you still just get the size of `bar` - polymorphism doesn't work at this level.
Mark Ransom
That's a good point. You need a virtual method in the derived classes to return their own size.
George Edison
Sorry, I was not talking about your code, just the above question.
George Edison
@elcuco: (Re revision comment.) So, who's the n00b again? This is a perfectly valid C program: `int main(int argc, char** argv) {return sizeof *argv;}`. Trust me, `sizeof` needs no brackets when referring to expressions (as opposed to type names).
Chris Jester-Young
Aside: Seeing `sizeof` used "as a function" is a serious peeve of mine. It's not a function; it's an operator. If you declare `int i`, both `sizeof i` and `sizeof (int)` should yield identical results. (I make a point to put a space after `sizeof` so nobody thinks it's a function, just as I do after `if`, `while`, or `for`.)
Chris Jester-Young
`int i = sizeof bar;` should be `size_t i = sizeof(bar);`. As everyone knows, parentheses are needed when the operand of `sizeof` is a type. And `sizeof` operator yields a value of `size_t` type.
Alok
+2  A: 

sizeof() determines the size at compile time.

It doesn't work until compile time, so you can't use it with the preprocessor.

R Samuel Klatchko
+1 for stating it can't be used with preprocessor.
Thomas Matthews
A: 

There is operator sizeof( int ), sizeof( char ) so I think that it is possible and call probably look like sizeof( MyClass )

Gaim
`sizeof` is an operator, not a function. You can't take the address of `sizeof` (whereas you can take the address of functions). :-P
Chris Jester-Young
You are right, I will fix it. Thank you for notice
Gaim
+7  A: 

To answer the updated question -- this may be overkill, but it will print out the sizes of your classes at compile time. There are a couple of undocumented compiler switches which will display the complete layouts of classes, including their sizes:

http://blogs.msdn.com/vcblog/archive/2007/05/17/diagnosing-hidden-odr-violations-in-visual-c-and-fixing-lnk2022.aspx

aalpern
+1 Props for the link!
John Dibling
Of course, I should have said that only applies to Visual C++, since the original question didn't specify a platform. I only work on Windows these days, hence my bias.
aalpern
+12  A: 

If you really need to to get sizeof(X) in the compiler output, you can use it as a parameter for an incomplete template type:

template<int s> struct Wow;
struct foo {
    int a,b;
};
Wow<sizeof(foo)> wow;

$ g++ -c test.cpp
test.cpp:5: error: aggregate ‘Wow<8> wow’ has incomplete type and cannot be defined
grep
+1 for being creative.
OneOfOne
That's what I'm looking for! Thanks!
Tim Gradwell
+1 for a combination of cleverness and luck
Potatoswatter
And if you don't want an error, but merely a warning, use it as the template parameter for a complete type, and subsequently define an otherwise unused object of that type. I.e. `Wow<sizeof(foo)> unused_warning;`.
MSalters