template<ClassName derivedClass>

If I can specify a base class for a template-based container, e.g.

container<Brick> wall;

And I have a class derived from Brick, such as CinderBrick, then can I populate the container, wall, with CinderBricks, just as I can do this (below)?

Brick* wall = new CinderBrick [20];

I don't think so. Then, its necessary to use templates (I'm making a class). But can't I do "template<ClassName derivedClass>" ? e.g.

1
2
3
4
5
6
7
template<Brick BrickType>
class Wall
{
	ConstructionPoint *a, *b;
	float thickness;
	container<BrickType> bricks;
};
Last edited on
closed account (o1vk4iN6)
Why not just use type brick ? This way you can have a multi-brick wall as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

class Wall
{
     container<Brick*> bricks;

public:

     template<class T> Brick* add()
     {
          bricks.push_back( new T );
          return bricks.back();
     }
};

Wall w;

w.add<CinderBrick>();


I mean there's a number of ways you can implement how to add a brick but you would need to have an array of pointers to type brick. If you want the wall to be all one type than you need to pass it as a class or typename.

1
2
3
4
5
6
7
8
9
10

template<class T>
class Wall
{
     static_assert( std::is_base_of<Brick, T>::value, "Wall<T>: T not derived from Brick" );

     container<T> bricks;

};
just as I can do this (below)?
Brick* wall = new CinderBrick [20];
You shouldn't do that.
Think what wall[1] is
ne555, can you be more specific?
It's a alignment problem. Think what happens if a CinderBrick is, like, 32 bytes and a simple Brick is 16.
Getting the first Brick is all ok, the extra CinderBrick 16bytes are further.
But, guess where are those extra 16bytes? They're in the place of the second Brick.

You can only do that if every class is of the same size, or if you have something like:

Brick ** wall = new wall[20]; wall[0] = new Brick; wall[1] = new CinderBrick; // etc etc


Or, let me humanize it:

Let's say your basical Brick is 1m long.
And your CinderBrick is 2m long.
Then you put 20 CinderBricks in a line. You get double length, but when you go checking for a Brick, you only can get half CinderBrick at a time. Even worse if CinderBrick's size isn't exactly twice the size of a Brick.
Last edited on
closed account (o1vk4iN6)
Unless CinderBrick is the same size as Brick (nothing is added) it is undefined behaviour. It'll be using the size of Brick to calculate the location in the array, therefore not taking into account that it is actually a CinderBrick.

1
2
3
4
5
6
7
8

// assume sizeof(Brick) == 4 and sizeof(CinderBrick) == 8

CinderBrick* c = new CinderBrick [20];
Brick* b = c;

c[10]; // offset of 76 bytes
b[10]; // offset of 36 bytes, therefore undefined behavior 
@EssGeEich
Yes I get it. But "Think what wall[1] is" seems like an ambiguous hint, so I wasn't sure what they meant.

C++'s metalanguage has me disappointed.
closed account (o1vk4iN6)
There is no need for templates if all the elements need to be derived from Brick, it is not unknown, using polymorphism and virtual member functions this can be done very easily. Use the tools for how they were made to be used, not how you want them to be used.
Topic archived. No new replies allowed.