Topic: Template Promotion was: constructor ambiguity


Author: rmartin@rcmcon.com (Robert Martin)
Date: Thu, 14 Oct 1993 15:49:04 GMT
Raw View
riordan@s6.math.umn.edu (James Riordan) writes:

>Is is possible to tell C++ which among several possible constructors
>to use?  I want to implement a matrix template class of homogeneous
>but indeterminate type so that I could say:

>  Matrix<double> foo;

>I would like objects of class Matrix<int> to become objects of class
>Matrix<double> or Matrix<Complex> automatically if needed as in:

No, there isn't a way.  Actually this is part of a bigger issue.

class B;
class D : public B;
template <class T> class Set;

D d;
B* bp = &d;  // because D* can be promoted to B*.

Set<D*> dset;
Set<B*>* bset = &dset;  // this doesn't work because a
                        // Set<D*> cannot be promoted to a
                        // Set<B*>.

This is unfortunate because a Set of D objects IS a set of B objects.

If a Set has a + operator to represent Union operations, then it would
be a nice idiom if:

class Animal;
class Dog : public Animal;
class Cat : public Animal;
Set<Dog*> dogs;
Set<Cat*> cats;

Set<Animal*> animals = dogs + cats;

But this doesn't work today because templates will not promote based
upon the promotability of their arguments.

Now, I haven't thought this through all the way.  I fear that there
are any number of very good arguments why template arguments should
not be the criterion for promoting template objects.  Has anybody else
given this any thought?

--
Robert Martin       | Design Consulting   | Training courses offered:
Object Mentor Assoc.| rmartin@rcmcon.com  |   Object Oriented Analysis
2080 Cranbrook Rd.  | Tel: (708) 918-1004 |   Object Oriented Design
Green Oaks IL 60048 | Fax: (708) 918-1023 |   C++




Author: g2devi@cdf.toronto.edu (Deviasse Robert N.)
Date: Thu, 14 Oct 1993 21:05:24 GMT
Raw View
In article <1993Oct14.154904.4632@rcmcon.com> rmartin@rcmcon.com (Robert Martin) writes:
>riordan@s6.math.umn.edu (James Riordan) writes:
>
>>Is is possible to tell C++ which among several possible constructors
>>to use?  I want to implement a matrix template class of homogeneous
>>but indeterminate type so that I could say:
>
>>  Matrix<double> foo;
>
>>I would like objects of class Matrix<int> to become objects of class
>>Matrix<double> or Matrix<Complex> automatically if needed as in:
>
>No, there isn't a way.  Actually this is part of a bigger issue.
>
>class B;
>class D : public B;
>template <class T> class Set;
>
>D d;
>B* bp = &d;  // because D* can be promoted to B*.
>
>Set<D*> dset;
>Set<B*>* bset = &dset;  // this doesn't work because a
>                        // Set<D*> cannot be promoted to a
>                        // Set<B*>.
>
>This is unfortunate because a Set of D objects IS a set of B objects.
>
>If a Set has a + operator to represent Union operations, then it would
>be a nice idiom if:
>
>class Animal;
>class Dog : public Animal;
>class Cat : public Animal;
>Set<Dog*> dogs;
>Set<Cat*> cats;
>
>Set<Animal*> animals = dogs + cats;
>
>But this doesn't work today because templates will not promote based
>upon the promotability of their arguments.
>
>Now, I haven't thought this through all the way.  I fear that there
>are any number of very good arguments why template arguments should
>not be the criterion for promoting template objects.  Has anybody else
>given this any thought?
>

Yes, it would cause problems with smart pointers. Allowing it would make

    Ptr<Derived*> d;
    Ptr<Base*> b = d;

legal while

    Derived** d;
    Base** b=d;

is illegal. It's a shame since this idiom would be very useful in allowing
smart pointers and references to be defined in a way that behaves more like
real pointers.

Hmmm, maybe there is a solution to this problem. Suppose we are yet another
keyword to C++: 'promotable' -- this would allow the programmer to choose
whether promotion based on the parameter is wanted. We could define:

    template<promotable class Reference_to_T> class Foo;
        to mean that Foo<T> is convertable to Foo<U> iff T is convertable to U
and
    template<promotable* class Pointer_to_T> class Foo;
        to mean that Foo<T> is convertable to Foo<U> iff T* is convertable to U*


Then a smart reference could be implemented as:
    template<promotable class T>
       class SmartReference {
          private:
            T& ref;
          // ...
       };

Then a smart pointer could be implemented as:
    template<promotable* class T>
       class SmartPointer {
          private:
            T* ref;
          // ...
       };


So that
    SmartPointer<Derived> d;
    SmartPointer<Base> b = d;     // OK

    SmartPointer<Derived*> d;
    SmartPointer<Base*> b = d;     // Error

By the definition of promotability, there should be no problem with type
safety. The problem has to do with semantics, how can one specific the
conversion operator, or is one even needed? It does not appear to be needed
here if elementwise promotion of all T members occurs, but is this sufficient
for the Set<T> example or will some other sort of conversion specification
be needed?

I mean, could Set<T> be promotable by defining it to be:
    template<promotable* class T>
       class Set{
          private:
             SetLink<T> headOfSetList;
          // ...
       };

where SetLink is also promotable? I'll have to look into this.

Any comments or counter-arguments?



>--
>Robert Martin       | Design Consulting   | Training courses offered:
>Object Mentor Assoc.| rmartin@rcmcon.com  |   Object Oriented Analysis
>2080 Cranbrook Rd.  | Tel: (708) 918-1004 |   Object Oriented Design
>Green Oaks IL 60048 | Fax: (708) 918-1023 |   C++


Take care
    Robert


--
/----------------------------------+------------------------------------------\
| Robert N. Deviasse               |"If we have to re-invent the wheel,       |
| EMAIL: g2devi@cdf.utoronto.ca    |  can we at least make it round this time"|
+----------------------------------+------------------------------------------/




Author: jss@lucid.com (Jerry Schwarz)
Date: Fri, 15 Oct 93 01:22:05 GMT
Raw View
In article <1993Oct14.154904.4632@rcmcon.com>, rmartin@rcmcon.com (Robert Martin) writes:
|>
|> No, there isn't a way.  Actually this is part of a bigger issue.
|>
|> class B;
|> class D : public B;
|> template <class T> class Set;
|>
|> D d;
|> B* bp = &d;  // because D* can be promoted to B*.
|>
|> Set<D*> dset;
|> Set<B*>* bset = &dset;  // this doesn't work because a
|>                         // Set<D*> cannot be promoted to a
|>                         // Set<B*>.
|>
|> This is unfortunate because a Set of D objects IS a set of B objects.
|>

Maybe. But unless you tightly constrain the kinds of members that
Set has, allowing the above can easily lead to a type violation.
Assume  Set has a member, "add", that allows me to add a T* to
it. Then

 class D1 : public B { ... } ;
 D1 d1 ;
 bset->add(&d1) ;

Now we've added a pointer to a D1 to dset, and that is obviously
a type violation.

  -- Jerry Schwarz