Gcc 4.x inheritance + template problem

I have maybe 15 years experience running g++ 3.xx and those before.

When g++ was updated to 4.xx I had a great many problems, most of all because
the linux that came with SuSE 10 marked all errors with inclusion between
ASCII 300's, I suppose gcc expected a change of colour, but my Linux did not
know how to handle those and outputted question marks instead, which
frightened me and I decided to wait for un update of gcc 4.

After maybe two years I now need to update my g++ 3 sources, but it asks me
"What is a SATA disk? " and similars.

I feel that all Linux releases follow Windows philosophy to generate more
money: every newer version looks nicer, shows more colours and more
gradutaions, but works poorer.

At present I use:

Linux 2.6.27.7-9-default #1 SMP 2008-12-04 18:10:04 +0100 x86_64 x86_64 x86_64 GNU/Linux
with gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux)

BUT
** It does not accept VectorInd::Size as being inherited from Vector, and
** enforces me to add "Vector <T*> :: " before every call to something from its parent.

I feel this conficts with the basic priciples of c++.
-----------------------------------------------------

******** Can anybody tell me what I do wrong? **************

Here it is:

quote
-----
template < class T >
class Vector { // Budd p 144

/*
* +-----------------+
* | # of elements |
* +-----------------+ +------------+
* | Pointer to Data | -----> | Data [ 0 ] |
* +-----------------+ +------------+
* | Data [ 1 ] |
* +------------+
* | |
*/

protected:

uint Partition ( uint, uint );
int Quicksort ( uint low, uint hgh );

public:

uint Size;
T * Data;
....
....
....
};

template < class T >
class VectorInd : public Vector < T* > {

public:
VectorInd ( uint Size = 0 );
VectorInd ( uint Size, T * * Data );
....
....
};

template < class T >
ofstream& VectorInd < T > :: Unload ( ofstream& os ) const {
os.write ( ( const char * ) & Vector <T*> ::Size, sizeof ( Vector <T*>::Size ) );
for ( uint count = 0; count < Vector <T*>::Size; count++ ) {
Vector <T*> :: Data [ count ] -> Unload ( os );
} // for
return os;
} // ofstream& VectorInd:: Unload ( ofstream& os ) const {


uquote
------

Nieuwenhuizen
2010-09-07
You can use this-> instead of Vector <T*> :: for member access
Yes, you are right thank you.

But it still conflicts with inheritance rules, or am I wrong?
Nieuwenhuizen
No, you have to specify that they are members of that object because template classes can be specialized so the compiler doesn't know if those members will be available
Dear Mr Bazzy

It is not clear to me.

Can you please give me a written or internet reference to understand the why not? I still have the feeling that we sacrifice a major property of object-orientation. My sources gave no problems whatsoever in gcc 3.xx.

Thanks a lot.
Nieuwenhuizen
jk@nieuwenhuizen-jk.nl
More info:
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18

nieuwenhuizenjk, your original code was not C++ standards compliant, but your code compiled fine
because neither was your old compiler. The newer GCC is more standards compliant, hence it exposed
your coding problem.

I have a lot to read now. Maybe I come back on it. Thanks a lot.

N
2010-09007T20:55

1. http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Name-lookup.html#Name-lookup
2. http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18

I quote from (1)
"The C++ standard prescribes ..."

and from (2):
class Xyz { ... }; ← global ("namespace scope") type
void f() { } ← global ("namespace scope") function

template<typename T>
class B {
public:
class Xyz { ... }; ← type nested in class B<T>
void f() { } ← member of class B<T>
};

template<typename T>
class D : public B<T> {
public:
void g()
{
Xyz x; ← suprise: you get the global Xyz!!
f(); ← suprise: you get the global f!!
}
};
-----

It is like the law: everybody has to obey it, even if it illogic, and I feel
it is. if we remove the "template ..." there is no surprise: B:f() has
priority on ::f() :

using namespace std;
#include <iostream>
void f ( ) { cout << "in global :: f()" << endl; }

class B {
public:
void f ( ) { cout << "in B:: f()" << endl; }
};

class D : public B {
public:
void g() {
f ( );
}
};

int main ( ) {
D MyD;
MyD.g();
return 1;
}

This outputs "in B:: f()"

OK?
-------------

I feel that several sections in Stroustrup ( The C++ ... ) are extremely
difficult to read, par 13.6 "Derivation and Templates" is one of them, but the
problem is not mentioned there.

What I am after is how to program 1 template procedure for <T> as well as for
<T*> that reads its input from T, and T* respectively. I can then sort
very large structs as fast as integers using the same procedure, swapping
their addresses instead of the whole strucs.

Stroustrup 13.3.2 seems to describe that, but I cannot see what he is up to.

Who helps me out?




Nieuwenhuizen
2010-09-10T12:58
Since the syntax for accessing elements of a T is different from that of accessing elements of a T* (namely, a
dereference is required), you need to introduce a level of indirection. I can't solve your entire problem for you,
but the gist is this:

Introduce two template wrapper classes. One takes a T (wraps a T), the other a T* (wraps a T*). Write operator()
on both, which returns a T& (or an operator() const which returns a T const&). Now you have a consistent interface
by which you can deal with both a T and a T*.

Topic archived. No new replies allowed.