Topic: Idea: "Array pointer type
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/04 Raw View
[ How to distinguish between pointer to object and
pointer into an array -- 3242432th ]
You are (about) the 3242432th person who proposes such
a thing. This is interresting exercice wrt to type
safety and understanding of pointers, but there are no
ways to do that w/o breaking virtually every program
which uses C arrays, including main (int, char**).
So, in one phrase: ``forget it''.
--
Valentin Bonnard
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/08/04 Raw View
In article <37A7002E.E2871A04@physik.tu-muenchen.de>,
Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
>
> My idea is to break up the current pointer type into an
> "ordinary pointer" and an "array pointer".
A nice objective, but before we take it any farther, what is the type of
the pointer returned in:
extern "C" char* getHostname() ;
Unless you can answer that one well, without loosing the other
advantages, forget it. (delete/delete[] isn't relevant here, but
presumably, pointer arithmetic would only be legal on an array pointer.)
The requirement to work with extern "C" isn't gratuious. Where else in
a C++ program would use use a C style array anyway?
--
James Kanze mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient e objet/
Beratung in objekt orientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/07 Raw View
Valentin Bonnard wrote:
>
> [ How to distinguish between pointer to object and
> pointer into an array -- 3242432th ]
Really? I seem only to remember "How to make an array
a first class type" - quite different, isn't it?
One point, though: I had forgotten a very important
conversion (for compatibility): There should, of course,
be a conversion T* to T[] as well (not only the other way
round). Of course, from a logical point, it would be
better to omit this, but for compatibility it's essencial.
>
> You are (about) the 3242432th person who proposes such
> a thing. This is interresting exercice wrt to type
> safety and understanding of pointers, but there are no
> ways to do that w/o breaking virtually every program
> which uses C arrays, including main (int, char**).
IMHO your claim is wrong. Indeed, with the added
conversion above, and the *trivial* additional rule
that both int main(int, char*[]) and int main(int, char**)
should be supported, we get:
- Programs which do not use arrays of derived classes
are not affected at all (there may be inserted implicit
casts from and to array pointers, but they are no-ops
at the code level, and the capabilities of both differ
only with derived/base conversions
- Programs which _do_ use arrays of derived classes
are _only_ affected, if they do the following:
class Base {};
class Derived: public Base {};
void foo(Base*);
void far(Derived arr[])
{
foo(arr); // gets illegal
}
Note that _only_ this special usage would break. As soon
as you do any of
- storing in a Derived* first and calling foo with that
- converting explicitly to Base* (or to Derived*)
- adding a number (even 0)
no error would arise. (Note that "Base* p= new Derived[10];"
is just a variation of the above - however, in this case
it's most likely an error - one that should be catched.)
I suspect that this very special case would not be _that_
frequent. Moreover, if it arises, it's easy to correct
(just replace arr by arr+0)
The other way I see how programs could break, is if they
use both of the now equivalent forms T[] and T* in
argument lists for declarations of the same function.
That's also easy to detect (the linker tells you the
function isn't there) and easy to resolve (change the
signature to use one form only - a good idea anyway).
>
> So, in one phrase: ``forget it''.
Why should I forget it, if I can correct it?
With the additional implicit cast above, it would IMHO
not break many programs, and even less well-written
programs.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/07 Raw View
James.Kanze@dresdner-bank.com wrote:
>
> In article <37A7002E.E2871A04@physik.tu-muenchen.de>,
> Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
> >
> > My idea is to break up the current pointer type into an
> > "ordinary pointer" and an "array pointer".
>
> A nice objective, but before we take it any farther, what is the type of
> the pointer returned in:
>
> extern "C" char* getHostname() ;
char*, of course.
Indeed, the array pointer type is only useful with derived
classes; those won't be returned by extern "C" functions
anyway.
>
> Unless you can answer that one well, without loosing the other
> advantages, forget it. (delete/delete[] isn't relevant here, but
> presumably, pointer arithmetic would only be legal on an array pointer.)
Quite the opposite: The array pointer does not "directly"
support pointer arithmetics, but it allows it through
implicit conversion to normal pointers (i.e., if p is a T[],
p+i means really (T*)p+i.
The array pointer is _not_ an abstraction of the concept
"iterator into array", but of the concept "pointer to an array".
The iterator function is still taken by ordinary pointers
(you cannot disallow pointer arithmetic on them anyway,
without breaking a considerable amount of code).
>
> The requirement to work with extern "C" isn't gratuious. Where else in
> a C++ program would use use a C style array anyway?
Whereever it fits?
Note that you can't f.ex. do a stack based vector
(you can put a vector object on the stack, of course,
but the data still is on the heap).
Even alloca doesn't help, since if you use it in an
allocator member function, the memory is destroyed on
return from that function.
But maybe it doesn't fit often enough anyway.
I guess before the STL, it would have been more
attractive ;-)
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/08/03 Raw View
My idea is to break up the current pointer type into an
"ordinary pointer" and an "array pointer". The ordinary
pointer would (for compatibility) behave as currently and
use the same syntax; the "array pointer" would, however,
behave different. A possible syntax (which might have
problems, though) could be
type var[]; // nothing between brackets!
The array new expression would return an array pointer;
using non-array delete on an array pointer would be a
syntax error (since an array pointer would never be the
result of a non-array new, using non-array delete on
an array pointer would always be an error; this error
can be caught by the compiler).
The array pointer would have the following properties:
- Implicit conversion to ordinary pointer to same type
(but not to ordinary pointer to base type).
- No pointer arithmetic, but the expression p+n
would still be allowed, through the conversion to
ordinary pointer (thus also allowing polymorphic
behaviour of the array elements).
- Dereferencing is allowed and yields the same result
as an ordinary pointer, including polymorphic behaviour.
- Explicit casts are allowed whenever the explicit cast
is allowed on the corresponding ordinary pointer, and
give the same results.
- Arrays decay to an array pointer instead of an ordinary
pointer. The resulting array pointer is then subject to
implicit conversions.
- The representation of ordinary pointers and array pointers
is the same.
The advantages of this new type are:
- Errors like "Base* p = new Derived[10];" are flagged
by the compiler
- If the result of "new T[]" is stored in "T p[]", then
delete p; will flag an error.
- A function can be assured that array operations will
not work on the wrong type, if "T x[]" is given in the
argument list. Since this is currently done in exactly
that situation, those functions would automatically
get increased safety. (If another syntax were chosen,
you still could get that improved safety by changing
the code).
The given syntax would, however, give some incompatibilities
with current C++, which however IMHO would be easy to resolve:
- Currently, the declarations "void f(int*)" and
"void f(int[])" declare the same function. The change
would result those functions to be different.
However, this error would be caught by the linker, and
changing it would be trivial (and improve the code
anyway IMHO)
- If the first element of an array (either declared
directly, or passed through array syntax into a
function) is assigned to an ordinary pointer to
base class, or such a pointer is initialized
with it (as in a function call with pass per value
pointer argument), this will be illegal. A simple
workaround is adding 0 to the pointer:
struct Base {};
struct Derived: Base {};
void foo(Base*);
void bar(Derived array[])
{
foo(array); // currently legal, would be illegal
foo(array+0); // would remain legal
}
There's another issue with this syntax, if the C9x
extension to allow "type var[]" at the end of a struct
is added to C++. There would be no way to resolve this
other than using a different syntax.
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/03 Raw View
In article <37A7002E.E2871A04@physik.tu-muenchen.de>, Christopher Eltschka
<celtschk@physik.tu-muenchen.de> wrote:
> My idea is to break up the current pointer type into an
> "ordinary pointer" and an "array pointer".
[snip]
> The advantages of this new type are:
>
> - Errors like "Base* p = new Derived[10];" are flagged
> by the compiler
> - If the result of "new T[]" is stored in "T p[]", then
> delete p; will flag an error.
> - A function can be assured that array operations will
> not work on the wrong type, if "T x[]" is given in the
> argument list. Since this is currently done in exactly
> that situation, those functions would automatically
> get increased safety. (If another syntax were chosen,
> you still could get that improved safety by changing
> the code).
What about the uses? As in, how much well-written code using ISO C++ would
even have a need for this? Is the extra type-safety gained the small
amount of code that would use it worth the cost of the feature? Could this
be achived with the language as it currently stands? i.e.
template<class T,std::size_t S>
struct array {
T data [S];
};
template<class T>
class array_ptr {
T* array;
template<typename T>
operator T () const; // not defined - error to call
public:
template<std::size_t S>
array_ptr( array<T,S>* p ) : array( p ) { }
array_ptr( std::size_t size ) : array( new T [size] ) { }
void destroy( array_ptr p ) {
delete [] p.array;
}
template<> // I'm not sure if this is required
operator T* () const { return array; }
T& operator [] ( std::size_t i ) { return array [i]; }
};
// usage
struct Base { };
struct Derived : Base { };
void f1( Base* );
void f2( Derived* );
void f3( array_ptr<Derived> );
void f() {
array<Derived,10> local_array;
array_ptr<Derived> array( 10 );
f1( array ); // error
f2( array ); // OK
f3( array ); // OK
f3( &local_array ); // OK
delete array; // error - which conversion operator to use?
array->destroy(); // OK
}
Just in writing this example, I see a blur between semantics one wants.
In the end, where does it really buy safety? A function may take a pointer
to an array, but assume the size of the array. No safety is given here.
One can already take a reference to an array. Maybe one would want to pass
a single object and a count of 1 to a function that dealt with an array. I
think, with the container/algorithm/iterator portion of the standard
library, uses of C-style arrays can be mostly eliminated.
[snip]
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]