Topic: newtype


Author: kon@iki.fi (Kalle Olavi Niemitalo)
Date: Tue, 27 Jan 2004 17:35:15 +0000 (UTC)
Raw View
rdsbrows@nospam.onet.pl ("Rafal Dabrowa") writes:

> Additionally, we are not able to create a template like:
>     template <class T> class new_type { /* ... */ }
> used like this:
>     typedef new_type<int> MONEY_T;
>     typedef new_type<int> WEIGHT_T;
> This class wouldn't behave as expected: both types are
> synonyms for new_type<int> and can be used
> interchangeably.

You could perhaps add a dummy parameter to the template.
The template would not actually use the parameter, but
different arguments would result in different types.

  template <class T, class tag> class new_type { /* ... */ };

  struct money_tag {};
  typedef new_type<int, money_tag> MONEY_T;

  struct weight_tag {};
  typedef new_type<int, weight_tag> WEIGHT_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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: bekkah@web.de (Helium)
Date: Tue, 3 Feb 2004 21:25:24 +0000 (UTC)
Raw View
> Ada has a possibility to derive a new type from an existing one.
> Derived type behaves like original, but, unlike a type defined by typedef,
> can't be used interchangeably with another derived types (unless
> explicitly casted). Why C++ does not have such possibility ?
> Suppose that we define such types like typedef, using "newtype" keyword:
>     newtype int MONEY_T;
>     newtype int WEIGHT_T;
>
>     void use_money(MONEY_T) { /* ... */ }
>     MONEY_T money;
>     WEIGHT_T weight;
>
>     use_money(money);    // OK
>     use_money(1234);    // OK
>     use_money(weight);    // oops! compilation error
>     use_money( static_cast<MONEY_T>(weight) );    // OK
>
> I think that such construction would allow to catch a bit more
> errors at compilation time.
>     Althrough we can create a class MONEY_T and
> WEIGHT_T, but why create a new, complicated class
> for state like "this is an int, but it keeps money only" ?
> Nobody does that. Instead, we are using often:
>     typedef int MONEY_T;
>     typedef int WEIGHT_T;
> and we think "this is a money" and "this is a weight".
> But compiler does not know our intentions - any mistake
> it compiles without problems.
> Additionally, we are not able to create a template like:
>     template <class T> class new_type { /* ... */ }
> used like this:
>     typedef new_type<int> MONEY_T;
>     typedef new_type<int> WEIGHT_T;
> This class wouldn't behave as expected: both types are
> synonyms for new_type<int> and can be used
> interchangeably.
>
But what happens, if I do the following

struct Foo {};
newtype Foo Bar {};

struct FooD : public Foo {};
struct BarD : public Bar {};  // allowed?

Bar * bar = new BarD; // allowed?
Foo * foo = new BarD; // allowed?

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: v.Abazarov@comAcast.net ("Victor Bazarov")
Date: Tue, 3 Feb 2004 22:34:30 +0000 (UTC)
Raw View
"Helium" <bekkah@web.de> wrote...
> > Ada has a possibility to derive a new type from an existing one.
> > Derived type behaves like original, but, unlike a type defined by
typedef,
> > can't be used interchangeably with another derived types (unless
> > explicitly casted). Why C++ does not have such possibility ?
> > Suppose that we define such types like typedef, using "newtype" keyword:
> >     newtype int MONEY_T;
> >     newtype int WEIGHT_T;
> >
> >     void use_money(MONEY_T) { /* ... */ }
> >     MONEY_T money;
> >     WEIGHT_T weight;
> >
> >     use_money(money);    // OK
> >     use_money(1234);    // OK
> >     use_money(weight);    // oops! compilation error
> >     use_money( static_cast<MONEY_T>(weight) );    // OK
> >
> > I think that such construction would allow to catch a bit more
> > errors at compilation time.
> >     Althrough we can create a class MONEY_T and
> > WEIGHT_T, but why create a new, complicated class
> > for state like "this is an int, but it keeps money only" ?
> > Nobody does that. Instead, we are using often:
> >     typedef int MONEY_T;
> >     typedef int WEIGHT_T;
> > and we think "this is a money" and "this is a weight".
> > But compiler does not know our intentions - any mistake
> > it compiles without problems.
> > Additionally, we are not able to create a template like:
> >     template <class T> class new_type { /* ... */ }
> > used like this:
> >     typedef new_type<int> MONEY_T;
> >     typedef new_type<int> WEIGHT_T;
> > This class wouldn't behave as expected: both types are
> > synonyms for new_type<int> and can be used
> > interchangeably.
> >
> But what happens, if I do the following
>
> struct Foo {};
> newtype Foo Bar {};

My guess is that you won't need the curly braces here.  Just

    newtype Foo Bar;

Now, Bar is a synonym of Foo in functional sense but cannot
be substituted for Foo where Foo is expected.  That's what
happens.

>
> struct FooD : public Foo {};
> struct BarD : public Bar {};  // allowed?

Why not?  'Bar' is a complete type, a mirror, so to speak, of
Foo.  If you can derive from Foo, you should be able to derive
from Bar.

>
> Bar * bar = new BarD; // allowed?

Sure.  Pointer-to-Derived to Pointer-to-Base conversion.

> Foo * foo = new BarD; // allowed?

I wouldn't think so.  Since Foo and Bar are not the same and
cannot be used in place of one another, there is no conversion
between a pointer to something derived from Bar into Foo.

Victor

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: bekkah@web.de (Helium)
Date: Wed, 4 Feb 2004 15:29:50 +0000 (UTC)
Raw View
> > But what happens, if I do the following
> >
> > struct Foo {};
> > newtype Foo Bar {};
>
> My guess is that you won't need the curly braces here.  Just
>
>     newtype Foo Bar;
>
> Now, Bar is a synonym of Foo in functional sense but cannot
> be substituted for Foo where Foo is expected.  That's what
> happens.

Oops, of course. Of course I ment

newtype Foo Bar;

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: technews@kangaroologic.com ("Jonathan Turkanis")
Date: Sun, 25 Jan 2004 20:04:52 +0000 (UTC)
Raw View
""Rafal Dabrowa"" <rdsbrows@nospam.onet.pl> wrote in message
news:buldfh$2u2$1@news.onet.pl...
>
> Ada has a possibility to derive a new type from an existing one.
> Derived type behaves like original, but, unlike a type defined by
typedef,
> can't be used interchangeably with another derived types (unless
> explicitly casted). Why C++ does not have such possibility ?
> Suppose that we define such types like typedef, using "newtype"
keyword:
>     newtype int MONEY_T;
>     newtype int WEIGHT_T;
>

You seem to be advocating "strong typedefs". This has been discussed
for C++, with the following syntax:

        strong_typedef int money_t;
        strong_typedef int weight_t;

See  "Asepcts of Forwarding" by  Lois Goldthwaite
(http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1395.txt).

Jonathan




---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rdsbrows@nospam.onet.pl ("Rafal Dabrowa")
Date: Fri, 23 Jan 2004 23:19:06 +0000 (UTC)
Raw View
Ada has a possibility to derive a new type from an existing one.
Derived type behaves like original, but, unlike a type defined by typedef,
can't be used interchangeably with another derived types (unless
explicitly casted). Why C++ does not have such possibility ?
Suppose that we define such types like typedef, using "newtype" keyword:
    newtype int MONEY_T;
    newtype int WEIGHT_T;

    void use_money(MONEY_T) { /* ... */ }
    MONEY_T money;
    WEIGHT_T weight;

    use_money(money);    // OK
    use_money(1234);    // OK
    use_money(weight);    // oops! compilation error
    use_money( static_cast<MONEY_T>(weight) );    // OK

I think that such construction would allow to catch a bit more
errors at compilation time.
    Althrough we can create a class MONEY_T and
WEIGHT_T, but why create a new, complicated class
for state like "this is an int, but it keeps money only" ?
Nobody does that. Instead, we are using often:
    typedef int MONEY_T;
    typedef int WEIGHT_T;
and we think "this is a money" and "this is a weight".
But compiler does not know our intentions - any mistake
it compiles without problems.
Additionally, we are not able to create a template like:
    template <class T> class new_type { /* ... */ }
used like this:
    typedef new_type<int> MONEY_T;
    typedef new_type<int> WEIGHT_T;
This class wouldn't behave as expected: both types are
synonyms for new_type<int> and can be used
interchangeably.


Rafal
--
sed -e s/s/a/g <my_address >my_right_address



---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]