Click here to Skip to main content
15,881,172 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi!

I wonder if there is any good way to get the largest size of some classes at compile time. The background to the problem is that I'm using an object pool were I need to set the size of the largest object that I will add.

At the moment I have an other project (which I first compile) were I print sizeof for all classes and pick the largest of them, however it's a bit exhausting since I add and remove classes too frequently for that to be conveniently. I'm aware of that I could use some temporary size until release but I was just wondering if that really was necessary.

If you have any good ideas I would really appreciate it.

*****************************************************************

Thank you all for the great answers! They have helped me a lot to understand how to continue from here.

*****************************************************************

Found exactly what I was looking for from the beginning at http://www.cplusplus.com/articles/EhvU7k9E/[^] even if I have got some (probably better) suggestions already. Unfortunately though Visual Studio still doesn't support Variadic templates so it's not an option at the moment anyway.

C++
template<typename... Arguments>
class VariadicTemplate{
private:
    static const unsigned short int size = sizeof...(Arguments);
};
Posted
Updated 3-Jul-13 5:51am
v4

If it's just "some classes" you can define a union of them and take the size of the union. That will give you the size of the biggest member of the union. And that size is even known at compile time.
C++
union U
{
   ClassA a;
   ClassB b;
   ClassC c;
};

size_t biggestSize = sizeof (U);
 
Share this answer
 
Comments
H.Brydon 1-Jul-13 14:14pm    
Great answer. I like that. I did it the hard way in an old allocator of mine. That trick would have saved me a lot of work. ... +5
WaZoX 1-Jul-13 15:26pm    
I thought of this myself actually but almost all the classes are using virtual functions. For some reason that's not possible to compile with visual studio so this isn't an option for me unfortunately. Apart from that it's a very clean and nice solution.

I get the following error for a basic class (called MyClassB) with one virtual member:
"IntelliSense: invalid union member -- class "MyClassB" has a disallowed member function"
nv3 1-Jul-13 16:36pm    
You are right. That approach only works for POD (plain old data) classes and not for classes having virtual functions (reason: there can only be one virtual function table pointer and the compiler would not know that you are not in the least interested in ever allocating that union). So the only crude alternative would be to write N sizeof statements and compute their max.
WaZoX 1-Jul-13 19:34pm    
Why can't it just overwrite the pointer to the virtual function table depending on which class that is "used/active"? Anyway I see that I didn't mentioned virtual members so I will accept this solution as well =)
nv3 2-Jul-13 6:29am    
If you tried to instatiate an object of type U the compiler had generate code to initialize the v-table pointer in the first word of the object. The problem is: It doesn't know which of the many v-tables to use, for ClassA, ClassB, ClassC ...? And that's why this construct is not allowed in C++.
Instead of allocating for the largest sized class, why can't you use an allocation pool for each class? If more than one class is the same size, you could use templates to have them use the same pool.

I've done this kind of thing before and it works well. Beware of alignment issues. Each allocation unit size should be a multiple of 8, and aligned to a double word boundary. If your class is of size 7 for example you need to round up the allocation size to (a multiple of) 8.
 
Share this answer
 
Comments
nv3 1-Jul-13 15:16pm    
That's also a good recommendation. I don't know if it applies in that case. But OP should certainly consider that solution.
WaZoX 1-Jul-13 15:33pm    
That's sounds like an acceptable solution but it needs a new template case for almost all new classes or I'm I wrong?
H.Brydon 1-Jul-13 17:19pm    
I went looking for the code I used in several places, and I see that there are some new strategies for C++11 which my code does not consider. From what I can see, there is some allocator logic in stl (which seems to be good) and also boost (which seems to be bad/buggy/unmaintained). I won't show you my code but will leave it to you and Google to find some code out there. One of the template based things that looks interesting can be found at http://stackoverflow.com/questions/6596575/c-custom-allocator-that-utilizes-a-underlying-memory-pool ...
There is no way provided by C++ to get statistical information like that for you.

You'll have to write it.

Inside your project you could have a singleton class that tracks the sizes, or the largest size, then query the sizeof each class.

I don't see a need for a separate app unless you need the value at compile time.

In the distant past when I needed buffer pools of this sort, I created more than one, each with a predetermined size. Then when allocating an object, I picked the pool that had a size that is just big enough to hold it.

Allocating pools as powers of 2 might work for you.

*********************

As mentioned in Solution 3...

Rounding up can give you a good spread on the pool size.

Here's a handy code fragment for doing this.
C++
auto newSize = ((((size - 1) >> 4) + 1) << 4);


What this code fragment does, is round up the size to the nearest multiple of sixteen.
Replacing the 4 with a 5 would round up to a multiple of 32 as it's base 2.
 
Share this answer
 
v3
Comments
WaZoX 1-Jul-13 15:38pm    
I really like the idea of allocating a few different pools and I guess that you actually could allocate them first when you have an object that doesn't fit one pool already existing. Really nice idea.
JackDingler 1-Jul-13 16:37pm    
BTW, you'll see multiple object pools in a lot of gaming code.
It's a common strategy.
WaZoX 1-Jul-13 19:23pm    
Thank you very much for your answer, it has been very helpful!
JackDingler 1-Jul-13 15:50pm    
Would the person who voted '1' on this solution provide a reason please, so that I can improve my responses in the future?
H.Brydon 1-Jul-13 17:16pm    
[Fixup: incorrect formula in first version of this...]
I think the formula I used for rounding up the size was

size_t s = (size + 7) / 8 * 8;

Brief table of values:

size s
==== ====
0 0
1 8
2 8
3 8
4 8
5 8
6 8
7 8
8 8
9 16
10 16
11 16
12 16
13 16
14 16
15 16
16 16

... a little less complicated.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900