Thread View: gnu.g++.help
2 messages
2 total messages
Started by Stefan Neis
Thu, 11 Jan 1996 15:43
Argument matching
Author: Stefan Neis
Date: Thu, 11 Jan 1996 15:43
Date: Thu, 11 Jan 1996 15:43
79 lines
3099 bytes
3099 bytes
Hi there,
I'm having an ugly problem with templates and inheritance. I mirrored
my problem by a less complicated --though useless -- example which
avoids using templates. Assume the following class hierarchie:
A B
|
Bderived
and let there be a constructor which makes a Bderived from A.
I hoped, the compiler would automatically convert A to Bderived (user
defined conv.) and then convert this to B (standard conversion, isn't
it?) if I give an "A" as argument to a function expecting a "B". But
this is obviously not the case -- neither with g++ nor with CC -- (see
the following example), so I assume that a user defined conversion
always has to be the last conversion that is applied to an
argument. Is this assumption correct (Couldn't find anything on this
in Stroustrup's "The C++ Programming Language")? If so, are there
plans to change this? I would find this kind of conversions extremely
useful for using templates, e.g. (to get to my original example) if
you want a "vector<int>" and a "vector<complex>", where complex is
intended to be some class realizing complex numbers, you would like to
have a automatic conversion from "vector<int>" to "vector<complex>"
and maybe "vector<complex>" should have additional functions. So I
wrote a "base_vector<T>" (corresponding to B) where all common
functions are included, vector inherits from this, and is specialised
for complex (corresponding to Bderived) and now the automatic
conversion from vector<int>(corresponding to A) to vector<complex>
doesn't work as I hoped it to do. Any Suggestions on how to circumvent
this problem? Is my problem really that unusual?
Stefan Neis
P.S.: I suppose, I could additionally define a "cast operator" from A to
the base_class B (constructor won't do, since B is intended
to be a template class...), but if I would derive Bderived by
several steps from B this would lead to programming the "same"
cast operator over and over again....
--------------------- EXAMPLE -----------------------------------
class A
{
int i;
public:
A(){}
A(int x){i=x;}
int get() const {return i;};
~A(){}
};
class B
{
long i; // using long instead of "complex" to get
// something that compiles more easily.
public:
B(){}
B(int x){i=x;}
~B(){}
friend B operator * (const B&, const B&);
};
class Bderived: public B
{
public:
Bderived():B(){}
Bderived(int x):B(x){}
Bderived(const A & x):B(x.get()){}
~Bderived(){}
};
main()
{ A testA(4);
Bderived testBder(5);
B testB;
testB = Bderived(testA) * testBder; // this -- of course -- does work.
testB = testA * testBder; // this won't compile at all.
}
Re: Argument matching
Author: Russell Blackadar
Date: Sat, 13 Jan 1996 02:31
Date: Sat, 13 Jan 1996 02:31
64 lines
3580 bytes
3580 bytes
Stefan Neis (neis@cs.uni-sb.de) wrote: : Hi there, : I'm having an ugly problem with templates and inheritance. I mirrored : my problem by a less complicated --though useless -- example which : avoids using templates. : A B : | : Bderived : and let there be a constructor which makes a Bderived from A. : : I hoped, the compiler would automatically convert A to Bderived (user : defined conv.) and then convert this to B (standard conversion, isn't : it?) if I give an "A" as argument to a function expecting a "B". Strictly speaking, it expects a const B&, and yes, you can call such a function with a temporary Bderived as argument. The trouble is, *any* class derived from B has this property. What kind of object should the compiler construct? I know, in your example, the situation is unambiguous, but that won't be true in general. Your explicit cast works because it tells the compiler you want, specifically, a Bderived object. : I hoped, the compiler would automatically convert A to Bderived (user : defined conv.) and then convert this to B (standard conversion, isn't : it?) if I give an "A" as argument to a function expecting a "B". But : this is obviously not the case -- neither with g++ nor with CC -- (see : the following example), so I assume that a user defined conversion : always has to be the last conversion that is applied to an : argument. Is this assumption correct (Couldn't find anything on this : in Stroustrup's "The C++ Programming Language")? Not quite. It's true when the conversion is via ctor, because of the potential ambiguity I mention above. But, for example, if you have defined an A::operator int(), then it's legal to use an A where where float is expected. The conversion to float happens after the conversion to int. If so, are there : plans to change this? I would find this kind of conversions extremely : useful for using templates, e.g. (to get to my original example) if : you want a "vector<int>" and a "vector<complex>", where complex is : intended to be some class realizing complex numbers, you would like to : have a automatic conversion from "vector<int>" to "vector<complex>" : and maybe "vector<complex>" should have additional functions. So I : wrote a "base_vector<T>" (corresponding to B) where all common : functions are included, vector inherits from this, and is specialised : for complex... Your idea (or something like it) has considerable merit, if you derive the template from a base class that is *not* a template. In other words, if there is functionality that any vector<T> will share regardless of T, put it in the base class and you'll get only one copy of the code generated, instead of a bazillion. In any case, you'll need to define the operators all at the vector<T> level, so that the argument and return types are right -- but probably many can be one-liners that invoke workhorse functions in the base class. Good luck! [code example deleted] -- Russell Blackadar, russell@mdli.com
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads