"Levent" <sl**@pitt.edu> wrote in message
news:d7**********@usenet01.srv.cis.pitt.edu...
Hi,
When compiled with gcc 3.3.3 and lower on various systems (tried cygwin,
linux, aix) the following code behaves strangely:
Well, then give gcc the prize becuse the other compilers failed the task.
#include <iostream>
class Foo {
public:
typedef int subs[3];
undefined behaviour, an array object is not an integer nor can it ever be.
typedef is meant to create a new type definition, not to act like a pointee
converter.
<snip>
int main()
{
int sz[]={10,20,30};
Why aren't you encapsulating the array container? Why bother write the
classes Foo and Bar otherwise?
Foo f;
f.callme(sz); // should print 30 and it does
Bar<Foo> b;
b.callme(sz); // should print 30 but it does not with gcc
return 0;
}
The problem is that `Bar<Foo>::callme' somehow accesses uninitized space
in memory instead of the one sz[] points to.
Because subs is passed as an integer to Bar<Foo>callme's parameter, subs is
not an array. A compiler that allows ...
typedef int subs[3];
.... is allowing undefined behaviour. C++ implies strict type checking, not a
particular compiler's version of type redefinitions.
Try the code below in all compilers mentioned above:
Note that an array is not the appropriate container here. A vector would
have been more usefull. Foo's constructor initializes the array's elements.
The member functions callme() only need a reference to the container's
index.
The array is a private member of the Foo type, and the Bar type is
*composed* of a templated member that must support the callme() member
function.
#include <iostream>
class Foo
{
int subs[3];
public:
Foo()
{
std::cout << "Foo ctor invoked\n";
subs[0] = 10;
subs[1] = 20;
subs[2] = 30;
}
void callme(const int& i) const
{
std::cout << subs[i] << std::endl;
}
};
template<class foo_type>
class Bar
{
foo_type t;
public:
Bar() : t() { std::cout << "Bar ctor invoked\n"; }
void callme(const int& i) const
{
t.callme(i);
}
};
int main()
{
Foo f;
f.callme(2); // should print 30
Bar<Foo> b;
b.callme(2); // should print 30
return 0;
}
/* output:
Foo ctor invoked
30
Foo ctor invoked
Bar ctor invoked
30
*/
A vector is a much better choice than an array. Also, if Foo and Bar are
meant to have an "is_a" relationship (a Bar is_a Foo, a Car is_a Vehicle, a
Circle is_a shape), then you should have Bar inherit from Foo instead.