Topic: Proposal for type-safe built-in arrays (long)


Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/02/16
Raw View
In the past C++ has broken some C/C++ programs in disallowing
unsafe implicit type convertions:

when                 convertion          break

beginning of C++     void* -> T*         virtually all C programs (1)
                                         (but no programs in the C
                                         programming language 2nd)

post-ARM             int -> enum         lots of code (well defined)

December DWP         "" is const char[]  code which isn't const-clean
                                         but which is well defined

There is still a hole in the C++ type system (inherited from C,
as usual), that there is no distinction betwen the type of:
(1) a polymorphic pointer and
(2) a pointer to an array.

void foo (Base*); // array of base (1) or
      // polymorphic ptr to base (2) ?

Base b;
foo (&b); // b is at the same time (1) and (2)

Derived d;
foo (&d); // d can only be (2), not checked by the compiler

Base b2[2]; // need at least 2 elements to have a real array
foo (b2); // b2 can only be (1)

Derived d2[2];
foo (d2); // cannot be (1) nor (2): undefined behaviour

void foo (Base* bp)
{
    bar t = bp[0];       // use (2)
    bp->virtualFunc (t); // use (1)
}

In this case it isn't even clear that foo (&d) is undefined;
this has to be strictly fordiden to make a change possible.

I suggest that two types are needed to express (1) and (2),
a syntax to express them, and a clear semantic distinction
betwen (1) and (2).

void foo1 (Base*);  // means (1)
void foo2 (Base[]); // means (2)

foo1 (&b); // OK
foo2 (&b); // impossible to convert Base* to Base[]

foo1 (&d); // OK, Derived* -> Base* convertion
foo2 (&d); // impossible to convert Derived* to Base[]

foo1 (b2); // impossible to convert Base[] to Base*
foo2 (b2); // OK

foo1 (d2); // impossible to convert Derived[] to Base*
foo2 (d2); // impossible to convert Derived[] to Base[]

void foo1 (Base* bp) // means (1)
{
    bar t = bp[0];       // wrong, use (2) but declared as (1)
    bp->virtualFunc (t); // OK
}

void foo2 (Base[] bp) // means (1)
{
    bar t = bp[0];       // OK
    bp->virtualFunc (t); // wrong, use (1) but declared as (2)
}

So (1) and (2) are clearly distinct.

The allowed operators would be:

T[]       operator+ (T[], size_t);
T[]       operator- (T[], size_t);
ptrdiff_t operator- (T[], T[]);
T&        operator[] (T[], ptrdiff_t);

T&        operator* (T*);

new return a T* (unchanged)
new[] would return a T[]

Also the following declaration won't be considered equivalent:

 Type elem;
 Type*const elemPtr = &elem;

 bar (elemPtr);

and

 Type elemArray[1];

 bar (elemArray);

So programs which use a normal variable as an array of one
element would break.

T[] could be considered:
- incomplete (cleaner)
- complete, sizeof (T[]) == sizeof (T*) (more compatible)

In the former case, the main declaration:

int main (int arg, char* argv[]);

would break and one would have to write

int main (int arg, char* (*argv)[]);

So it may change the language too much (but would give
much cleaner array parameter semantic).

So T[] has a function parameter must mean 'pointer to array of
unknown size of T'.

What do you think about that ?

Of course vector<> works well but:

- exception safety is a problem; new[] is garantied to handle
  an exception correctly (destroy only constructed objects);
  OTOH is will be solved (one day)

- vector<> is very powerfull and all this power may not be
  needed for a typical (compile-time or run-time) fixed size
  array

Note: one could do something even better if the containner type
(array) was distinct from the iterator type (pointer to an
element); *, +, - would only be defined on an iterator and
[] would be defined on a containner (which has value semantic).

I'd like to hear opinions from both language layers and
programmers (assuming these are disjoint sets ;-).

--

Valentin Bonnard
mailto:bonnardv@pratique.fr
http://www.pratique.fr/~bonnardv (Informations sur le C++ en Francais)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: boukanov@sentef2.fi.uib.no (Igor Boukanov)
Date: 1997/02/22
Raw View
Nice idea that can remove a lot of problems and potential erros
but it will never happen...

Regards, Igor Boukanov.
igor.boukanov@fi.uib.no
http://www.fi.uib.no/~boukanov/

P.S.
Maybe G++?
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]