comp.lang.ada
 help / color / mirror / Atom feed
* Type safety, C++ and code generation
@ 2006-04-27 10:35 Maciej Sobczak
  2006-04-27 13:19 ` REH
  0 siblings, 1 reply; 29+ messages in thread
From: Maciej Sobczak @ 2006-04-27 10:35 UTC (permalink / raw)


Hi,

I have developed a simple code generator that helps me significantly 
raise the level of type safety in C++:

http://www.msobczak.com/prog/typegen/

The whole idea was in some way inspired by Ada, so I hope to get some 
constructive criticism and comments from you - that's why I post it 
here. Please look at it from the perspective of Ada programmer.

(And taking into account the fact that some of you are also C++ 
programmers, you might actually find it interesting or even useful.)

-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 10:35 Type safety, C++ and code generation Maciej Sobczak
@ 2006-04-27 13:19 ` REH
  2006-04-27 14:08   ` Maciej Sobczak
  0 siblings, 1 reply; 29+ messages in thread
From: REH @ 2006-04-27 13:19 UTC (permalink / raw)



Maciej Sobczak wrote:
> Hi,
>
> I have developed a simple code generator that helps me significantly
> raise the level of type safety in C++:
>
> http://www.msobczak.com/prog/typegen/
>
> The whole idea was in some way inspired by Ada, so I hope to get some
> constructive criticism and comments from you - that's why I post it
> here. Please look at it from the perspective of Ada programmer.
>
> (And taking into account the fact that some of you are also C++
> programmers, you might actually find it interesting or even useful.)
>
> --
> Maciej Sobczak : http://www.msobczak.com/
> Programming    : http://www.msobczak.com/prog/

You maybe interested in a C++ class that I wrote.  It creates range and
overflow checked integer types.  The interesting thing about the class
is that it uses templates to do static analysis on expressions to
remove unnecessary checks at compile time.

For example:

typedef ranged_type<unsigned, 0, 100> R;
R x, y, z;  // The variables are defaulted to the
            // minimum of the range which in this
            // case is 0.  Sometime later these
            // variables are initialized.  Their
            // actual values do not matter for
            // this example.

const R a = 5, b = 7, c = 1;
R r = ((x + a) * (y + b)) / (z - c);

For the above, all overflow checks are removed, except for
divide-by-zero, negative values on the subtraction, and the upper range
of the result when assigning to r.

If you are interested, it can be found here:
http://www.richherrick.com/software/herrick_library.html


REH




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 13:19 ` REH
@ 2006-04-27 14:08   ` Maciej Sobczak
  2006-04-27 14:33     ` REH
                       ` (2 more replies)
  0 siblings, 3 replies; 29+ messages in thread
From: Maciej Sobczak @ 2006-04-27 14:08 UTC (permalink / raw)


REH wrote:

>>http://www.msobczak.com/prog/typegen/

> You maybe interested in a C++ class that I wrote.

Been there, done that:

http://www.msobczak.com/prog/downloads.html

(see safetypes.tar.gz and range.tar.gz)

I have dropped this idea because I think that the external code 
generator is much more flexible and more powerful with regard to the 
type safety that can be gained. Range checking is just one little part 
of what is needed. Template classes are fine if you can afford limiting 
yourself only to this little part, but that's not usually the case.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 14:08   ` Maciej Sobczak
@ 2006-04-27 14:33     ` REH
  2006-04-27 15:16       ` Maciej Sobczak
  2006-04-27 14:47     ` REH
  2006-04-27 15:10     ` REH
  2 siblings, 1 reply; 29+ messages in thread
From: REH @ 2006-04-27 14:33 UTC (permalink / raw)



Maciej Sobczak wrote:
> REH wrote:
>
> >>http://www.msobczak.com/prog/typegen/
>
> > You maybe interested in a C++ class that I wrote.
>
> Been there, done that:
>
> http://www.msobczak.com/prog/downloads.html
>
> (see safetypes.tar.gz and range.tar.gz)

I don't see where you've "done that."

>
> I have dropped this idea because I think that the external code
> generator is much more flexible and more powerful with regard to the
> type safety that can be gained. Range checking is just one little part
> of what is needed. Template classes are fine if you can afford limiting
> yourself only to this little part, but that's not usually the case.

I never said it was the end-all-be-all, just thought you may be
interested.  I don't know what you think templates are limiting you to.




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 14:08   ` Maciej Sobczak
  2006-04-27 14:33     ` REH
@ 2006-04-27 14:47     ` REH
  2006-04-27 15:10     ` REH
  2 siblings, 0 replies; 29+ messages in thread
From: REH @ 2006-04-27 14:47 UTC (permalink / raw)



Maciej Sobczak wrote:
> REH wrote:
>
> >>http://www.msobczak.com/prog/typegen/
>
> > You maybe interested in a C++ class that I wrote.
>
> Been there, done that:
>
> http://www.msobczak.com/prog/downloads.html
>
> (see safetypes.tar.gz and range.tar.gz)
>
> I have dropped this idea because I think that the external code
> generator is much more flexible and more powerful with regard to the
> type safety that can be gained. Range checking is just one little part
> of what is needed. Template classes are fine if you can afford limiting
> yourself only to this little part, but that's not usually the case.
>
>
> --
I just took a look at the code to pointed to above.  It is much
different then mine:
1) yours allows for undefined behavior by not checking for overflows
before doing the operations.
2) yours does not eliminate unnecessary checks.
3) yours does not allow intermidate results to exceed the bounds of the
range.  For example, given a variable x, with a range of [0, 100],
yours will fail on x = (x * 1000) / 1000, mine will not.
4) yours does not allow for types larger than long, such as unsigned
long or implementation-specific types such as long long.
5) yours does not check for division-by-zero.

Think you are being dismissive without even looking at it.
REH




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 14:08   ` Maciej Sobczak
  2006-04-27 14:33     ` REH
  2006-04-27 14:47     ` REH
@ 2006-04-27 15:10     ` REH
  2006-04-28  6:22       ` Maciej Sobczak
  2 siblings, 1 reply; 29+ messages in thread
From: REH @ 2006-04-27 15:10 UTC (permalink / raw)



Maciej Sobczak wrote:
> REH wrote:
>
> >>http://www.msobczak.com/prog/typegen/
>
> > You maybe interested in a C++ class that I wrote.
>
> Been there, done that:
>
> http://www.msobczak.com/prog/downloads.html
>
> (see safetypes.tar.gz and range.tar.gz)
>
> I have dropped this idea because I think that the external code
> generator is much more flexible and more powerful with regard to the
> type safety that can be gained. Range checking is just one little part
> of what is needed. Template classes are fine if you can afford limiting
> yourself only to this little part, but that's not usually the case.
>
>
Not to beat a dead horse, but your logic is also flawed in that it will
not detect overflows.  If an operation overflows, and wraps around into
range, your code will be non-the-wiser.

REH




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 14:33     ` REH
@ 2006-04-27 15:16       ` Maciej Sobczak
  2006-04-27 15:39         ` Georg Bauhaus
                           ` (3 more replies)
  0 siblings, 4 replies; 29+ messages in thread
From: Maciej Sobczak @ 2006-04-27 15:16 UTC (permalink / raw)


REH wrote:

>>>>http://www.msobczak.com/prog/typegen/
>>
>>>You maybe interested in a C++ class that I wrote.
>>
>>Been there, done that:
>>
>>http://www.msobczak.com/prog/downloads.html
>>
>>(see safetypes.tar.gz and range.tar.gz)
> 
> 
> I don't see where you've "done that."

The template class that implements range checking?

>>I have dropped this idea because I think that the external code
>>generator is much more flexible and more powerful with regard to the
>>type safety that can be gained. Range checking is just one little part
>>of what is needed. Template classes are fine if you can afford limiting
>>yourself only to this little part, but that's not usually the case.
> 
> I never said it was the end-all-be-all, just thought you may be
> interested.  I don't know what you think templates are limiting you to.

It's not about templates themselves, but rather about the whole approach.

What about making different types really distinct?

typedef ranged_type<int, 0, 100> R1;
typedef ranged_type<int, 0, 100> R2;
typedef ranged_type<int, 0, 101> R3;


Above, R1 and R2 are *equal* to the compiler, but R3 is distinct from 
the other two. This is or can be problematic in those contexts where you 
would rather expect them all to be different from each other - 
especially when you think in terms of different *domains*, no matter 
what is their range of values.

Another problem is that the range, as a set of values, is not the only 
thing that constitues a type - you also need to define the set of legal 
operations. The problem is that I usually want them to be different in 
each type.
Consider this:

type ranged_type<int, 0, 250> Speed;
Speed s1, s2, s3; // with some values
s1 = s2 + s3; // OK
s1 = s2 * s3; // not OK

The addition is fine, but the multiplication should not be provided, 
because speed multiplied by speed is not a speed. Can you extend your 
class so that the compiler will refuse to compile the second operation 
above?
(Ada, anyone? :) )

Another problem is variation of the behaviour in the out-of-range 
condition. What should happen then? Throw an exception? That's only one 
of at least four different options I can imagine, and also not the one I 
would choose most of the time. Does your class allow variations here?
(Ada, anyone? :) )


And so on - all this *can* be done with templates, but at some point 
this approach just saturates and the code becomes a nightmare. Not 
mentioning the error messages that you get from the compiler (and the 
whole purpose of this is to actually get *useful* error messages, 
right?). And not mentioning the compilation time.
These are exactly the factors that limit the practical useability of the 
template approach and that's why I claim that external code generator 
can be much more powerful.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 15:16       ` Maciej Sobczak
@ 2006-04-27 15:39         ` Georg Bauhaus
  2006-04-28  5:57           ` Maciej Sobczak
  2006-04-27 16:05         ` REH
                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 29+ messages in thread
From: Georg Bauhaus @ 2006-04-27 15:39 UTC (permalink / raw)


Maciej Sobczak wrote:

> type ranged_type<int, 0, 250> Speed;
> Speed s1, s2, s3; // with some values
> s1 = s2 + s3; // OK
> s1 = s2 * s3; // not OK
> 
> The addition is fine, but the multiplication should not be provided,
> because speed multiplied by speed is not a speed. Can you extend your
> class so that the compiler will refuse to compile the second operation
> above?
> (Ada, anyone? :) )

Just so it is visible:


procedure useop is

   s1, s2, s3: SPEED;  -- with some values

begin
   s3 := s1 * s2;
end useop;

     8.    s3 := s1 * s2;
                    |
        >>> cannot call abstract subprogram "*"

where

package Op is

   type SPEED is range 0 .. 250;

   function "*"(a, b: SPEED) return SPEED is abstract;

end Op;



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 15:16       ` Maciej Sobczak
  2006-04-27 15:39         ` Georg Bauhaus
@ 2006-04-27 16:05         ` REH
  2006-04-28  6:17           ` Maciej Sobczak
  2006-04-30 14:40         ` adaworks
  2006-04-30 18:14         ` Martin Krischik
  3 siblings, 1 reply; 29+ messages in thread
From: REH @ 2006-04-27 16:05 UTC (permalink / raw)



Maciej Sobczak wrote:
> REH wrote:
>
> > I don't see where you've "done that."
>
> The template class that implements range checking?

NO, a class that uses template to ELIMINATE unnecessary checks.

> What about making different types really distinct?
>
> typedef ranged_type<int, 0, 100> R1;
> typedef ranged_type<int, 0, 100> R2;
> typedef ranged_type<int, 0, 101> R3;

My code uses this technique if you want truely unqiue types:

class R1_unique{};
class R2_unique{};
typedef ranged_type<int, 0, 100, R1_unique> R1;
typedef ranged_type<int, 0, 100, R2_unique> R2;


>
> Another problem is that the range, as a set of values, is not the only
> thing that constitues a type - you also need to define the set of legal
> operations. The problem is that I usually want them to be different in
> each type.
> Consider this:
>
> type ranged_type<int, 0, 250> Speed;
> Speed s1, s2, s3; // with some values
> s1 = s2 + s3; // OK
> s1 = s2 * s3; // not OK
>
> The addition is fine, but the multiplication should not be provided,
> because speed multiplied by speed is not a speed. Can you extend your
> class so that the compiler will refuse to compile the second operation
> above?

Yes, you derive from the class and put the multiplication operator in
the private scope.

> Another problem is variation of the behaviour in the out-of-range
> condition. What should happen then? Throw an exception? That's only one
> of at least four different options I can imagine, and also not the one I
> would choose most of the time. Does your class allow variations here?

Yes, the template takes a traits class.  If allow modification of
various behaviors, such as what should be done with an out-of-range
value, an overflow condition, a divide-by-zero, etc.

>
> And so on - all this *can* be done with templates, but at some point
> this approach just saturates and the code becomes a nightmare. Not
> mentioning the error messages that you get from the compiler (and the
> whole purpose of this is to actually get *useful* error messages,
> right?). And not mentioning the compilation time.

I've heard all these things.  That may have been true with older
compilers.  They are a lot better today.  

REH




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 15:39         ` Georg Bauhaus
@ 2006-04-28  5:57           ` Maciej Sobczak
  2006-04-28 12:16             ` Georg Bauhaus
  0 siblings, 1 reply; 29+ messages in thread
From: Maciej Sobczak @ 2006-04-28  5:57 UTC (permalink / raw)


Georg Bauhaus wrote:

>>type ranged_type<int, 0, 250> Speed;
>>Speed s1, s2, s3; // with some values
>>s1 = s2 + s3; // OK
>>s1 = s2 * s3; // not OK
>>
>>The addition is fine, but the multiplication should not be provided,
>>because speed multiplied by speed is not a speed. Can you extend your
>>class so that the compiler will refuse to compile the second operation
>>above?
>>(Ada, anyone? :) )
> 
> 
> Just so it is visible:
> 
> 
> procedure useop is
> 
>    s1, s2, s3: SPEED;  -- with some values
> 
> begin
>    s3 := s1 * s2;
> end useop;
> 
>      8.    s3 := s1 * s2;
>                     |
>         >>> cannot call abstract subprogram "*"
> 
> where
> 
> package Op is
> 
>    type SPEED is range 0 .. 250;
> 
>    function "*"(a, b: SPEED) return SPEED is abstract;
> 
> end Op;

I like it, although there is some potential problem with this approach. 
It uses the "negative logic" - in other words, specifies what is 
forbidden, not what is allowed - so it's more prone to errors than the 
"positive logic", where you specify what *is* supported instead. In the 
"positive logic" approach you can start with the default setting (no 
operations) and the compiler will point you to each new operation usage 
in your code - then, you can either consciously extend the type 
definition to cover the new use case or reject it if it was a bug. It's 
much more cumbersome with the "negative logic", where the default 
setting provides no protection at all.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 16:05         ` REH
@ 2006-04-28  6:17           ` Maciej Sobczak
  0 siblings, 0 replies; 29+ messages in thread
From: Maciej Sobczak @ 2006-04-28  6:17 UTC (permalink / raw)


REH wrote:

>>>I don't see where you've "done that."
>>
>>The template class that implements range checking?
> 
> NO, a class that uses template to ELIMINATE unnecessary checks.

As I've said, I dropped this idea (using templates and metaprogramming 
techniques as a basis for building safer type system - this is what I 
mean by "done that"), because for me it doesn't scale.

>>What about making different types really distinct?
>>
>>typedef ranged_type<int, 0, 100> R1;
>>typedef ranged_type<int, 0, 100> R2;
>>typedef ranged_type<int, 0, 101> R3;
> 
> My code uses this technique if you want truely unqiue types:
> 
> class R1_unique{};
> class R2_unique{};
> typedef ranged_type<int, 0, 100, R1_unique> R1;
> typedef ranged_type<int, 0, 100, R2_unique> R2;

Of course, but this requires increased involvement of the user. Above, 
it is necessary to define two things to achieve what is conceptually 
only one goal. This is one of the limiting factors of this approach - it 
quickly "saturates" and becomes a maintenance nighmare for both the 
library writer and its users.

I akcnowledge that either the language has to inherently support this 
kind of stuff (like Ada does), or it's better to step *outside* of the 
language and use metamodels and some generation techniques.

>>Consider this:
>>
>>type ranged_type<int, 0, 250> Speed;
>>Speed s1, s2, s3; // with some values
>>s1 = s2 + s3; // OK
>>s1 = s2 * s3; // not OK
>>
>>The addition is fine, but the multiplication should not be provided,
>>because speed multiplied by speed is not a speed. Can you extend your
>>class so that the compiler will refuse to compile the second operation
>>above?
> 
> Yes, you derive from the class and put the multiplication operator in
> the private scope.

Which is the "negative logic" (see my answer to Georg Bauhaus) and it 
also creates additional entity (the derived class) for reasons that have 
nothing to do with the original design. What about the base class, which 
still supports the unwanted operations?

What about this:

Velocity v;
Duration t;
Distance d = v * t; // OK
Distance d = v + t; // not OK

Now, the operation involves three types. Derivation and messing with 
private specifier is not a very scalable solution.


>>Another problem is variation of the behaviour in the out-of-range
>>condition. What should happen then? Throw an exception? That's only one
>>of at least four different options I can imagine, and also not the one I
>>would choose most of the time. Does your class allow variations here?
> 
> Yes, the template takes a traits class.  If allow modification of
> various behaviors, such as what should be done with an out-of-range
> value, an overflow condition, a divide-by-zero, etc.

Fine (and I've "done that").
And now, with all this traits-and-derivation-and-tagging-and-what-not, 
is it easy for the user to understand the typical compiler error message?


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 15:10     ` REH
@ 2006-04-28  6:22       ` Maciej Sobczak
  0 siblings, 0 replies; 29+ messages in thread
From: Maciej Sobczak @ 2006-04-28  6:22 UTC (permalink / raw)


REH wrote:

> your logic is also flawed in that it will
> not detect overflows

Because it's not within the responsibilities of the class that is 
supposed to implement ranges.
The overflow is what happens (or not!) on the level of the underlying type.

If this has the overflow problems:

typedef range<int, 0, 100> R;

then the solution to those problems is this:

typedef range<my_int_with_overflow_protection, 0, 100> R;

or this:

typedef range<big_int, 0, 100> R;

or even this:

typedef range<overflow_protected<int>, 0, 100> R;

and so on - but whatever it is, it's not within the responsibilities of 
the range<T> class, which is only supposed to implement ranges on top of 
some given underlying type.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-28  5:57           ` Maciej Sobczak
@ 2006-04-28 12:16             ` Georg Bauhaus
  2006-04-28 12:37               ` brian.b.mcguinness
  2006-04-29 21:28               ` Florian Weimer
  0 siblings, 2 replies; 29+ messages in thread
From: Georg Bauhaus @ 2006-04-28 12:16 UTC (permalink / raw)


On Fri, 2006-04-28 at 07:57 +0200, Maciej Sobczak wrote:


> >    function "*"(a, b: SPEED) return SPEED is abstract;

> I like it, although there is some potential problem with this approach. 
> It uses the "negative logic"

Yes, there is negative logic, which invites mistakes.

And probably this isn't going to be changed, because language
designers somehow seem to think that they must provider what
they think are the usual arithmetic operations. Strangely,
they don't count actual uses, or invent mathematical structures
that reflect computing reality in a field.
How many times does "/" occur in your average computer 
program?
Irrational traditionalism in computer science, school kid's
math habits, or faulty ritual?






^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-28 12:16             ` Georg Bauhaus
@ 2006-04-28 12:37               ` brian.b.mcguinness
  2006-04-28 17:04                 ` Georg Bauhaus
  2006-04-28 18:50                 ` Jeffrey R. Carter
  2006-04-29 21:28               ` Florian Weimer
  1 sibling, 2 replies; 29+ messages in thread
From: brian.b.mcguinness @ 2006-04-28 12:37 UTC (permalink / raw)



Georg Bauhaus wrote:
> How many times does "/" occur in your average computer
> program?

That depends on what field you're working in.  If you're writing
compilers you may not need it very often.  If you're calculating
the positions of objects in the sky it comes up quite often.

One solution to the problem would be to provide a new keyword for
defining types with no default operations.  Only the operations you
explicitly defined would be available.

--- Brian




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-28 12:37               ` brian.b.mcguinness
@ 2006-04-28 17:04                 ` Georg Bauhaus
  2006-04-28 18:50                 ` Jeffrey R. Carter
  1 sibling, 0 replies; 29+ messages in thread
From: Georg Bauhaus @ 2006-04-28 17:04 UTC (permalink / raw)


On Fri, 2006-04-28 at 05:37 -0700, brian.b.mcguinness@lmco.com wrote:
> Georg Bauhaus wrote:
> > How many times does "/" occur in your average computer
> > program?
> 
> That depends on what field you're working in. 

True. Yet, I'd have to speculate that "general purpose" design 
is then influenced strongly by a particular field :)


> One solution to the problem would be to provide a new keyword for
> defining types with no default operations.  Only the operations you
> explicitly defined would be available.

I wonder whether it wouldn't be more flexible to use the
regular language means for defining types with operations,
and no predefined operations. Then provide some core packages
for "numbers with an arithmetical interface".


-- Georg 





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-28 12:37               ` brian.b.mcguinness
  2006-04-28 17:04                 ` Georg Bauhaus
@ 2006-04-28 18:50                 ` Jeffrey R. Carter
  2006-04-28 19:07                   ` Randy Brukardt
  2006-04-28 19:55                   ` Dmitry A. Kazakov
  1 sibling, 2 replies; 29+ messages in thread
From: Jeffrey R. Carter @ 2006-04-28 18:50 UTC (permalink / raw)


brian.b.mcguinness@lmco.com wrote:
> 
> One solution to the problem would be to provide a new keyword for
> defining types with no default operations.  Only the operations you
> explicitly defined would be available.

You mean like "limited private"?

-- 
Jeff Carter
"Blessed is just about anyone with a vested interest in the status quo."
Monty Python's Life of Brian
73



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-28 18:50                 ` Jeffrey R. Carter
@ 2006-04-28 19:07                   ` Randy Brukardt
  2006-04-28 19:46                     ` Robert A Duff
  2006-04-28 19:55                   ` Dmitry A. Kazakov
  1 sibling, 1 reply; 29+ messages in thread
From: Randy Brukardt @ 2006-04-28 19:07 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.not.jrcarter@acm.not.spam.org> wrote in message
news:7ut4g.921904$x96.7750@attbi_s72...
> brian.b.mcguinness@lmco.com wrote:
> >
> > One solution to the problem would be to provide a new keyword for
> > defining types with no default operations.  Only the operations you
> > explicitly defined would be available.
>
> You mean like "limited private"?

Right. The problem with "limited private" is the loss of numeric literals
(and string literals in another use). Usually, it's been thought that the
solution is to somehow provide literals for private types. OTOH, no one has
ever made that work out well enough to get it into Ada, so perhaps a
radically different approach is needed.

But careful: the operators come with generic formal types, so there would
have to be restrictions on formals that are similar to whatever is defined
for types:

    type Int is range 1 .. 10 without operators;

could not match

   type An_Int is range <>;

since An_Int has the usual operators. (And for compatibility reasons, that
couldn't change.)

there would have to be new formal kinds like

   type An_Int is range <> without operators;

to support matching for these types. (If you wanted to import the operators
defined for Int, you'd need to use a generic derived type.)

                         Randy.





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-28 19:07                   ` Randy Brukardt
@ 2006-04-28 19:46                     ` Robert A Duff
  0 siblings, 0 replies; 29+ messages in thread
From: Robert A Duff @ 2006-04-28 19:46 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> Right. The problem with "limited private" is the loss of numeric literals
> (and string literals in another use).

Right.  And case statements.  And arrays indexed by the type.  Etc.

>     type Int is range 1 .. 10 without operators;

I wonder whether this "without operators" syntax forbids the use of
attributes ('Succ, for example).

- Bob



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-28 18:50                 ` Jeffrey R. Carter
  2006-04-28 19:07                   ` Randy Brukardt
@ 2006-04-28 19:55                   ` Dmitry A. Kazakov
  1 sibling, 0 replies; 29+ messages in thread
From: Dmitry A. Kazakov @ 2006-04-28 19:55 UTC (permalink / raw)


On Fri, 28 Apr 2006 18:50:43 GMT, Jeffrey R. Carter wrote:

> brian.b.mcguinness@lmco.com wrote:
>> 
>> One solution to the problem would be to provide a new keyword for
>> defining types with no default operations.  Only the operations you
>> explicitly defined would be available.
> 
> You mean like "limited private"?

I don't think that would be a good idea.
Ada.Finalization.Limited_Controlled is a better way. The language offers an
abstract base type to derive from. No keywords needed.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-28 12:16             ` Georg Bauhaus
  2006-04-28 12:37               ` brian.b.mcguinness
@ 2006-04-29 21:28               ` Florian Weimer
  1 sibling, 0 replies; 29+ messages in thread
From: Florian Weimer @ 2006-04-29 21:28 UTC (permalink / raw)


* Georg Bauhaus:

> How many times does "/" occur in your average computer 
> program?

I use it quite often to implement right bit shifts. 8-/



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 15:16       ` Maciej Sobczak
  2006-04-27 15:39         ` Georg Bauhaus
  2006-04-27 16:05         ` REH
@ 2006-04-30 14:40         ` adaworks
  2006-04-30 15:23           ` REH
  2006-04-30 18:14         ` Martin Krischik
  3 siblings, 1 reply; 29+ messages in thread
From: adaworks @ 2006-04-30 14:40 UTC (permalink / raw)



"Maciej Sobczak" <no.spam@no.spam.com> wrote in message 
news:e2qn8t$n13$1@sunnews.cern.ch...
>
> What about making different types really distinct?
>
> typedef ranged_type<int, 0, 100> R1;
> typedef ranged_type<int, 0, 100> R2;
> typedef ranged_type<int, 0, 101> R3;
>
>
> Above, R1 and R2 are *equal* to the compiler, but R3 is distinct from the 
> other two.
This example raises the issue of structural equivalence versus
name equivalence.  In Ada R1 and R2 would not be
equivalent.

Ada is designed for name equivalence.    Most other languages
are designed for structural equivalence.    In this respect, Ada
continues to be just a wee bit more type safe than languages
designed for structural equivalence.

Richard Riehle 





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-30 14:40         ` adaworks
@ 2006-04-30 15:23           ` REH
  0 siblings, 0 replies; 29+ messages in thread
From: REH @ 2006-04-30 15:23 UTC (permalink / raw)



<adaworks@sbcglobal.net> wrote in message 
news:o%35g.64094$_S7.49734@newssvr14.news.prodigy.com...
>
> "Maciej Sobczak" <no.spam@no.spam.com> wrote in message 
> news:e2qn8t$n13$1@sunnews.cern.ch...
>>
>> What about making different types really distinct?
>>
>> typedef ranged_type<int, 0, 100> R1;
>> typedef ranged_type<int, 0, 100> R2;
>> typedef ranged_type<int, 0, 101> R3;
>>
>>
>> Above, R1 and R2 are *equal* to the compiler, but R3 is distinct from the 
>> other two.
> This example raises the issue of structural equivalence versus
> name equivalence.  In Ada R1 and R2 would not be
> equivalent.
>
> Ada is designed for name equivalence.    Most other languages
> are designed for structural equivalence.    In this respect, Ada
> continues to be just a wee bit more type safe than languages
> designed for structural equivalence.
>
> Richard Riehle

C++ does not use structural equivalence (nor does C).  It too uses name 
equivalence.  The problem is that typedef does not introduce a new name, but 
an alias.  The only way to introduce a new name is via enum, struct, class, 
or union.  templates also introduce new names, but instantiation with the 
same set of parameters are of the same name.  structs defined with the exact 
same fields but different names, are different.

REH





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-27 15:16       ` Maciej Sobczak
                           ` (2 preceding siblings ...)
  2006-04-30 14:40         ` adaworks
@ 2006-04-30 18:14         ` Martin Krischik
  2006-05-02  6:27           ` Maciej Sobczak
  3 siblings, 1 reply; 29+ messages in thread
From: Martin Krischik @ 2006-04-30 18:14 UTC (permalink / raw)


Maciej Sobczak wrote:

> What about making different types really distinct?
> 
> typedef ranged_type<int, 0, 100> R1;
> typedef ranged_type<int, 0, 100> R2;
> typedef ranged_type<int, 0, 101> R3;
> 
> 
> Above, R1 and R2 are equal to the compiler, but R3 is distinct from
> the other two. This is or can be problematic in those contexts where you
> would rather expect them all to be different from each other -
> especially when you think in terms of different *domains*, no matter
> what is their range of values.

This is because "typdef" in C++ is "subtype" in Ada. You would need:

class R1 : ranged_type<int, 0, 100> {};
class R2 : ranged_type<int, 0, 100> {};
class R3 : ranged_type<int, 0, 101> {};

to create new types.

Martin
-- 
mailto://krischik@users.sourceforge.net
Ada programming at: http://ada.krischik.com



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-04-30 18:14         ` Martin Krischik
@ 2006-05-02  6:27           ` Maciej Sobczak
  2006-05-02 13:33             ` REH
  0 siblings, 1 reply; 29+ messages in thread
From: Maciej Sobczak @ 2006-05-02  6:27 UTC (permalink / raw)


Martin Krischik wrote:

>>What about making different types really distinct?
>>
>>typedef ranged_type<int, 0, 100> R1;
>>typedef ranged_type<int, 0, 100> R2;
>>typedef ranged_type<int, 0, 101> R3;
>>
>>
>>Above, R1 and R2 are equal to the compiler

> This is because "typdef" in C++ is "subtype" in Ada.

Not really - you cannot add constraints with typedef. ;)

> You would need:
> 
> class R1 : ranged_type<int, 0, 100> {};
> class R2 : ranged_type<int, 0, 100> {};
> class R3 : ranged_type<int, 0, 101> {};
> 
> to create new types.

Except that those new types would be problematic to use with operations 
that are already defined for ranged_type (especially those which return 
ranged_type), because there is no implicit conversion to the derived class.


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-05-02  6:27           ` Maciej Sobczak
@ 2006-05-02 13:33             ` REH
  2006-05-02 15:05               ` Maciej Sobczak
  2006-05-02 16:50               ` Martin Krischik
  0 siblings, 2 replies; 29+ messages in thread
From: REH @ 2006-05-02 13:33 UTC (permalink / raw)



Maciej Sobczak wrote:
> Martin Krischik wrote:
>
> >>What about making different types really distinct?
> >>
> >>typedef ranged_type<int, 0, 100> R1;
> >>typedef ranged_type<int, 0, 100> R2;
> >>typedef ranged_type<int, 0, 101> R3;
> >>
> >>
> >>Above, R1 and R2 are equal to the compiler
>
> > This is because "typdef" in C++ is "subtype" in Ada.
>
> Not really - you cannot add constraints with typedef. ;)
>
> > You would need:
> >
> > class R1 : ranged_type<int, 0, 100> {};
> > class R2 : ranged_type<int, 0, 100> {};
> > class R3 : ranged_type<int, 0, 101> {};
> >
> > to create new types.
>
> Except that those new types would be problematic to use with operations
> that are already defined for ranged_type (especially those which return
> ranged_type), because there is no implicit conversion to the derived class.
>
That's not true.  operators are usually defined using references.  A
reference to a child class is alway implicitly convertable to a
reference to its parent class.  The only issues with the above are: 1)
it should use public inheritance, not private to allow the user access
to any member function that may be defined (i.e., member operators).
2) it has no constructors, because they are not inherited. 3) assigning
the result back to an object of the child class requires a constructor
to be defined.

REH




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-05-02 13:33             ` REH
@ 2006-05-02 15:05               ` Maciej Sobczak
  2006-05-02 15:54                 ` REH
  2006-05-02 16:50               ` Martin Krischik
  1 sibling, 1 reply; 29+ messages in thread
From: Maciej Sobczak @ 2006-05-02 15:05 UTC (permalink / raw)


REH wrote:

>>>class R1 : ranged_type<int, 0, 100> {};
>>>class R2 : ranged_type<int, 0, 100> {};
>>>class R3 : ranged_type<int, 0, 101> {};
>>>
>>>to create new types.
>>
>>Except that those new types would be problematic to use with operations
>>that are already defined for ranged_type (especially those which return
>>ranged_type), because there is no implicit conversion to the derived class.
> 
> That's not true.  operators are usually defined using references.

As written above: "especially those which return ranged_type".

// some operation on the range type (can be a template)
ranged_type<int, 0, 100> foo() {/* ... */}

// some "new type"
class R : ranged_type<int, 0, 100> {};

R r = foo(); // bang!


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-05-02 15:05               ` Maciej Sobczak
@ 2006-05-02 15:54                 ` REH
  0 siblings, 0 replies; 29+ messages in thread
From: REH @ 2006-05-02 15:54 UTC (permalink / raw)



Maciej Sobczak wrote:
> REH wrote:
>
> >>>class R1 : ranged_type<int, 0, 100> {};
> >>>class R2 : ranged_type<int, 0, 100> {};
> >>>class R3 : ranged_type<int, 0, 101> {};
> >>>
> >>>to create new types.
> >>
> >>Except that those new types would be problematic to use with operations
> >>that are already defined for ranged_type (especially those which return
> >>ranged_type), because there is no implicit conversion to the derived class.
> >
> > That's not true.  operators are usually defined using references.
>
> As written above: "especially those which return ranged_type".
>
> // some operation on the range type (can be a template)
> ranged_type<int, 0, 100> foo() {/* ... */}
>
> // some "new type"
> class R : ranged_type<int, 0, 100> {};
>
> R r = foo(); // bang!
>

Yes, which is why I said that one of the problems was that it was
missing necessary constructors.

REH




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-05-02 13:33             ` REH
  2006-05-02 15:05               ` Maciej Sobczak
@ 2006-05-02 16:50               ` Martin Krischik
  2006-05-02 19:50                 ` REH
  1 sibling, 1 reply; 29+ messages in thread
From: Martin Krischik @ 2006-05-02 16:50 UTC (permalink / raw)


REH wrote:

> 1)
> it should use public inheritance, not private to allow the user access
> to any member function that may be defined (i.e., member operators).

Code sniplets newsgroups should not be considered complete or perfect and
well I have not typed in "private" explicitly....

Martin
-- 
mailto://krischik@users.sourceforge.net
Ada programming at: http://ada.krischik.com



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Type safety, C++ and code generation
  2006-05-02 16:50               ` Martin Krischik
@ 2006-05-02 19:50                 ` REH
  0 siblings, 0 replies; 29+ messages in thread
From: REH @ 2006-05-02 19:50 UTC (permalink / raw)



Martin Krischik wrote:
> REH wrote:
>
> > 1)
> > it should use public inheritance, not private to allow the user access
> > to any member function that may be defined (i.e., member operators).
>
> Code sniplets newsgroups should not be considered complete or perfect and
> well I have not typed in "private" explicitly....
>

No, but the code should by unambiguous.  How was I to know you meant
for the base class to be publically inherited?  You don't need to
explicitly type private.  It is the default.  

REH




^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2006-05-02 19:50 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-04-27 10:35 Type safety, C++ and code generation Maciej Sobczak
2006-04-27 13:19 ` REH
2006-04-27 14:08   ` Maciej Sobczak
2006-04-27 14:33     ` REH
2006-04-27 15:16       ` Maciej Sobczak
2006-04-27 15:39         ` Georg Bauhaus
2006-04-28  5:57           ` Maciej Sobczak
2006-04-28 12:16             ` Georg Bauhaus
2006-04-28 12:37               ` brian.b.mcguinness
2006-04-28 17:04                 ` Georg Bauhaus
2006-04-28 18:50                 ` Jeffrey R. Carter
2006-04-28 19:07                   ` Randy Brukardt
2006-04-28 19:46                     ` Robert A Duff
2006-04-28 19:55                   ` Dmitry A. Kazakov
2006-04-29 21:28               ` Florian Weimer
2006-04-27 16:05         ` REH
2006-04-28  6:17           ` Maciej Sobczak
2006-04-30 14:40         ` adaworks
2006-04-30 15:23           ` REH
2006-04-30 18:14         ` Martin Krischik
2006-05-02  6:27           ` Maciej Sobczak
2006-05-02 13:33             ` REH
2006-05-02 15:05               ` Maciej Sobczak
2006-05-02 15:54                 ` REH
2006-05-02 16:50               ` Martin Krischik
2006-05-02 19:50                 ` REH
2006-04-27 14:47     ` REH
2006-04-27 15:10     ` REH
2006-04-28  6:22       ` Maciej Sobczak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox