Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Template And Arrays

Reply
Thread Tools

Template And Arrays

 
 
Marcelo De Brito
Guest
Posts: n/a
 
      05-26-2009
Hi!

I have created a template in which there is a generic vector/array
that can hold any type defined by the programmer or built-in types.
When I define the vector/array using built-in types (int, double,
etc.), I must insert data of the respective type in it. But when I
define the array using a programmer defined type (e.g., a class), I
can access the class' members even though I did not insert any object
in it! See the lines of code below for a better explanation.

class B { //Programmer defined type.
public:
B() {};
B(int idd) : id(idd) {};
B(const B&) {};
virtual ~B() {};
void setid(int idd) {id = idd;}
void dummy() {cout << "B::dummy()" << " " << "id = " << id <<
endl;}
private:
int id;
};

template <class T, int size = 10>
class D1 {
public:
D1() : index(0) {};
D1(const D1&) {};
virtual ~D1() {};
T vt[size];
void push(T* i) {
vt[index] = *i;
index++;
}
void exvet() {
for(int i = 0; i<index; i++)
cout << "vt[" << i << "] = " << vt[i] << endl;
}
void vetsize() {cout << size << endl;}
private:
int index;

};

int main()
{
D1<int, 5> od4; //First with int.

for(int i = 0; i<5; i++)
od4.push(&i); //<- Inserting ints in the array. Fine.

od4.exvet(); //<- Shows the ints int the array, Fine too.

D1<B, 10> od5; //Now with the programmer defined type.

for(int i = 0; i<10; i++)
od5.vt[i].dummy(); //<- !!!!!!!HERE!!!!!! It compiles and run!
}

In my mind, when I declared "D1<B, 10> od5", I allocated memory for 10
elements of the type "B" -- as I did when I defined for the int type
"D1<int, 5> od4". BUT, in the "int" case, I had to insert data in the
vector "vt" of the template in order to properly access it. Therefore,
how could I access the members of "od5" if I did not insert any class
"B" object in the respective array "vt"?

Wouldn't a more suited way for this case be:

D1<B, 10> od5;

for(int i = 0; i<10; i++)
od5.push(new B); //Inserting class B objects.
for(int i = 0; i<10; i++)
od5.vt[i].dummy(); //Accessing members of the objects inserted.

How about it??

I appreciate any comment, suggestion, etc.

Thank You!

Marcelo
 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      05-26-2009
* Marcelo De Brito:
>
> I have created a template in which there is a generic vector/array


It's not a "generic vector/array", it is a fixed size raw array.


> that can hold any type defined by the programmer or built-in types.


Well, this is subtle, but it can't hold just any type. If the type in question
requires construction but does not support default construction, then there's no
way to instantiate the array. std::vector solves this by using, well, advanced
techniques, but std::vector still doesn't support non-copyable element type.


> When I define the vector/array using built-in types (int, double,
> etc.), I must insert data of the respective type in it.


OK, taken as description of your class' interface.


> But when I
> define the array using a programmer defined type (e.g., a class), I
> can access the class' members even though I did not insert any object
> in it!


That's your choice as designer of the class.

It's a bad choice.

Don't expose implementation details.


> See the lines of code below for a better explanation.
>
> class B { //Programmer defined type.
> public:
> B() {};


This leaves the 'id' member with indeterminate value => later UB.


> B(int idd) : id(idd) {};


OK.


> B(const B&) {};


This leaves the 'id' member with indeterminate value => later UB.


> virtual ~B() {};
> void setid(int idd) {id = idd;}
> void dummy() {cout << "B::dummy()" << " " << "id = " << id <<
> endl;}
> private:
> int id;
> };
>
> template <class T, int size = 10>
> class D1 {
> public:
> D1() : index(0) {};


OK.


> D1(const D1&) {};


This leaves the 'index' member with indeterminate value => later UB.

Depending on the type T it also leaves the 'vt' member with indeterminate values
(which is OK), or default constructed values (which impacts negatively on
efficiency).


> virtual ~D1() {};


OK.


> T vt[size];


This is a raw array of constant size.


> void push(T* i) {
> vt[index] = *i;
> index++;
> }


This is bad design. It requires client code to use the address operator, and it
opens the door for nullpointer argument, cuasing UB (most likely a crash). Make
the formal argument type 'T const&'.



> void exvet() {
> for(int i = 0; i<index; i++)
> cout << "vt[" << i << "] = " << vt[i] << endl;
> }


OK, debugging?


> void vetsize() {cout << size << endl;}


OK, more debugging?


> private:
> int index;
>
> };
>
> int main()
> {
> D1<int, 5> od4; //First with int.
>
> for(int i = 0; i<5; i++)
> od4.push(&i); //<- Inserting ints in the array. Fine.
>
> od4.exvet(); //<- Shows the ints int the array, Fine too.
>
> D1<B, 10> od5; //Now with the programmer defined type.
>
> for(int i = 0; i<10; i++)
> od5.vt[i].dummy(); //<- !!!!!!!HERE!!!!!! It compiles and run!


So?


> }
>
> In my mind, when I declared "D1<B, 10> od5", I allocated memory for 10
> elements of the type "B" -- as I did when I defined for the int type
> "D1<int, 5> od4". BUT, in the "int" case, I had to insert data in the
> vector "vt" of the template in order to properly access it.


No, you didn't.


> Therefore,
> how could I access the members of "od5" if I did not insert any class
> "B" object in the respective array "vt"?


You can access the elements because you haven't prevented access.

That's your choice as class designer.

Make the array 'private' (or 'protected') to prevent client code access.



> Wouldn't a more suited way for this case be:
>
> D1<B, 10> od5;
>
> for(int i = 0; i<10; i++)
> od5.push(new B); //Inserting class B objects.
> for(int i = 0; i<10; i++)
> od5.vt[i].dummy(); //Accessing members of the objects inserted.
>
> How about it??


Well, how about it?

Have you tried actually writing that (and compiling and running)?


Cheers & hth.,

- Alf

--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! Just going there is good. Linking
to it is even better! Thanks in advance!
 
Reply With Quote
 
 
 
 
Marcelo De Brito
Guest
Posts: n/a
 
      05-27-2009
Hi, Alf!

Thank you very much for your comments and explanations!

Concerning all the UB stuffs you aforementioned, it was just my
lazyness of not taking them out when copying and pasting the code
here.

By the way, I appreciate your comments. Very useful, indeed.

What I have not understood so far is the possibility of accessing
class' members through an array that was just allocated, but has no
objects inserted in it.

However, I think the line "D1<B, 10> od5" automatically does all the
allocation and object creation work. It will allocate 10 positions in
the array "vt" and will declare/define them as the type "B", since
that is the way it is defined in the template, and, as the default
constructor "B()" needs no arguments, it is possible to the array "vt"
to be created holding 10 class "B" objects. The line inside the
template:

T vt[size];

Does all the necessary work and it is not needed to insert any objects
in it, since they have already been inserted/created. I think.

Have I got it right?

Thank You!

Marcelo
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      05-27-2009
* Marcelo De Brito:
> Hi, Alf!
>
> Thank you very much for your comments and explanations!
>
> Concerning all the UB stuffs you aforementioned, it was just my
> lazyness of not taking them out when copying and pasting the code
> here.
>
> By the way, I appreciate your comments. Very useful, indeed.
>
> What I have not understood so far is the possibility of accessing
> class' members through an array that was just allocated, but has no
> objects inserted in it.
>
> However, I think the line "D1<B, 10> od5" automatically does all the
> allocation and object creation work. It will allocate 10 positions in
> the array "vt" and will declare/define them as the type "B", since
> that is the way it is defined in the template, and, as the default
> constructor "B()" needs no arguments, it is possible to the array "vt"
> to be created holding 10 class "B" objects. The line inside the
> template:
>
> T vt[size];
>
> Does all the necessary work and it is not needed to insert any objects
> in it, since they have already been inserted/created. I think.
>
> Have I got it right?


Yep.


Cheers & hth.,

- Alf

--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! Just going there is good. Linking
to it is even better! Thanks in advance!
 
Reply With Quote
 
Bart van Ingen Schenau
Guest
Posts: n/a
 
      05-27-2009
Marcelo De Brito wrote:

> Hi, Alf!
>
> Thank you very much for your comments and explanations!
>
> Concerning all the UB stuffs you aforementioned, it was just my
> lazyness of not taking them out when copying and pasting the code
> here.
>
> By the way, I appreciate your comments. Very useful, indeed.
>
> What I have not understood so far is the possibility of accessing
> class' members through an array that was just allocated, but has no
> objects inserted in it.
>
> However, I think the line "D1<B, 10> od5" automatically does all the
> allocation and object creation work. It will allocate 10 positions in
> the array "vt" and will declare/define them as the type "B", since
> that is the way it is defined in the template, and, as the default
> constructor "B()" needs no arguments, it is possible to the array "vt"
> to be created holding 10 class "B" objects. The line inside the
> template:
>
> T vt[size];
>
> Does all the necessary work and it is not needed to insert any objects
> in it, since they have already been inserted/created. I think.
>
> Have I got it right?


Yes.
And to see that the array always initially contains default-constructed
objects, try commenting out the B::B() constructor. Then the code will
no longer compile.

>
> Thank You!
>
> Marcelo


Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-27-2009
On May 27, 12:52 am, Marcelo De Brito <(E-Mail Removed)> wrote:

> I have created a template in which there is a generic
> vector/array that can hold any type defined by the programmer
> or built-in types. When I define the vector/array using
> built-in types (int, double, etc.), I must insert data of the
> respective type in it. But when I define the array using a
> programmer defined type (e.g., a class), I can access the
> class' members even though I did not insert any object in it!
> See the lines of code below for a better explanation.


> class B { //Programmer defined type.
> public:
> B() {};
> B(int idd) : id(idd) {};
> B(const B&) {};
> virtual ~B() {};
> void setid(int idd) {id = idd;}
> void dummy() {cout << "B::dummy()" << " " << "id = " << id <<
> endl;}
> private:
> int id;
> };


> template <class T, int size = 10>
> class D1 {
> public:
> D1() : index(0) {};
> D1(const D1&) {};
> virtual ~D1() {};
> T vt[size];
> void push(T* i) {
> vt[index] = *i;
> index++;
> }
> void exvet() {
> for(int i = 0; i<index; i++)
> cout << "vt[" << i << "] = " << vt[i] << endl;
> }
> void vetsize() {cout << size << endl;}
> private:
> int index;
> };


> int main()
> {
> D1<int, 5> od4; //First with int.


> for(int i = 0; i<5; i++)
> od4.push(&i); //<- Inserting ints in the array. Fine.


> od4.exvet(); //<- Shows the ints int the array, Fine too.


> D1<B, 10> od5; //Now with the programmer defined type.


> for(int i = 0; i<10; i++)
> od5.vt[i].dummy(); //<- !!!!!!!HERE!!!!!! It compiles and run!


Why shouldn't it? You've created an array of 10 B in od5.vt.

> }


> In my mind, when I declared "D1<B, 10> od5", I allocated
> memory for 10 elements of the type "B" -- as I did when I
> defined for the int type "D1<int, 5> od4".


In both cases, you've created an array of N elements. In the
case of int, the elements are not initialized (since int has a
trivial constructor), and reading the values before writing them
would be undefined behavior (in practice, you'll normally just
get a random value). In the case of B, the object has a user
defined constructor, and that will be used to initialize them.
(Given that the user defined constructor doesn't initialize B::id,
accessing B::id before setting it will still result in undefined
behavior.)

> BUT, in the "int" case, I had to insert data in the vector
> "vt" of the template in order to properly access it.


No. No more so than in the case of B.

> Therefore, how could I access the members of "od5" if I did
> not insert any class "B" object in the respective array "vt"?


The same way you could have accessed od4[ 3 ] before inserting
any data.

> Wouldn't a more suited way for this case be:


> D1<B, 10> od5;


> for(int i = 0; i<10; i++)
> od5.push(new B); //Inserting class B objects.


Why the new? (For that matter, why does push take a pointer?)

> for(int i = 0; i<10; i++)
> od5.vt[i].dummy(); //Accessing members of the objects inserted.


When you define an array, all of the elements are created. If
the array is of a non-POD class type, then its constructors are
called; otherwise, it has an indeterminate value; reading this
value is undefined behavior (unless the object has character
type).

It's possible to separate allocation from initialization, but it
requires a bit more work. The array itself must be declared as
unsigned char, and steps must be taken to ensure that it is
properly aligned. And placement new must be used for
initialization.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Marcelo De Brito
Guest
Posts: n/a
 
      05-27-2009
Hi, James!

>Why the new? (For that matter, why does push take a pointer?)


It was just some implementation details for the code work a little
more without needing to debug it. It is just a code test and not the
final product.

Without the "(new B)" the code didn't compile.

By the way, thank you very much for your explanations!

Thank You!

Marcelo
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Multidimensional arrays and arrays of arrays Philipp Java 21 01-20-2009 08:33 AM
How to use the template member function of a template in the memberfunction of another template class? Peng Yu C++ 3 10-26-2008 03:51 PM
template template arguments: expected a class template, got `Component<T1, T2, T3> gary.bernstein@gmail.com C++ 1 06-08-2007 07:10 AM
Re: A Newbie Question about template template template tom_usenet C++ 0 07-24-2003 12:06 PM
Re: A Newbie Question about template template template Chris Theis C++ 2 07-24-2003 09:42 AM



Advertisments