Thread overview
typedef alternative
Aug 15, 2010
Yao G.
Aug 15, 2010
Jonathan M Davis
Aug 15, 2010
Yao G.
Aug 15, 2010
Jonathan M Davis
Aug 15, 2010
Yao G.
Aug 15, 2010
Yao G.
Aug 15, 2010
sybrandy
Aug 15, 2010
Yao G.
August 15, 2010
Hello.

Is there an alternative to typedef? I need to define three structs that have exactly the same methods and properties, yet represent different stuff.

Example:
---
struct Foo
{
    this( int f ) {
        _foo = f;
    }

    int asNumber() {
        return _foo;
    }

    private immutable int _foo;
}

// This should be typedef, but as it's going to be deprecated...
alias Foo Year;
alias Foo Month;
alias Foo Day;


void bar( Year y, Month m, Day d ) {
    // ...
}

// This should compile, obviously.
bar( Year(2010), Month(8), Day(14) );

// But this shouldn't
bar( Day(1), Year(1), Month(1) );
---

So, what options do I have? I know that typedef is scheduled to deprecation, so I would like to know if there's something else.


-- 
Yao G.
August 15, 2010
Okay, I'm not familiar with what typedef is supposed to have done in D. I've only ever used alias. But what is wrong with

On Saturday 14 August 2010 17:47:44 Yao G. wrote:
> // This should be typedef, but as it's going to be deprecated...
> alias Foo Year;
> alias Foo Month;
> alias Foo Day;

Is it because Year, Month, Day, and Foo are still completely interchangeable, and you should be able to do things like pass a Year to function that takes a Month? Are you looking to create a new type that while technically identical to another type is not considered the same as that type by the type system?

- Jonathan M Davis
August 15, 2010
On Sat, 14 Aug 2010 20:05:04 -0500, Jonathan M Davis <jmdavisprog@gmail.com> wrote:

> [snip]
>
> Are you looking to create a new type that while technically identical to
> another type is not considered the same as that type by the type system?
>
> - Jonathan M Davis

Yes, This is exactly what I want. I need, for example, that if you pass a Year instance to the Month parameter, generate a compiler error.


-- 
Yao G.
August 15, 2010
I can't recall if you can do this with structs, but if you use classes, you should be able to define a "Date Part" class that has all of the methods and data you want.  Then, you just derive three sub-classes.

For example (and I hope the syntax is right):

class DatePart
{
   this(int f)
   {
      _foo = f;
   }

   int asNumber() { return _foo; }

   immutable int _foo;
}

class Year: DatePart {}

class Month: DatePart {}

class Day: DatePart {}

Casey

On 08/14/2010 08:47 PM, Yao G. wrote:
> Hello.
>
> Is there an alternative to typedef? I need to define three structs that
> have exactly the same methods and properties, yet represent different
> stuff.
>
> Example:
> ---
> struct Foo
> {
> this( int f ) {
> _foo = f;
> }
>
> int asNumber() {
> return _foo;
> }
>
> private immutable int _foo;
> }
>
> // This should be typedef, but as it's going to be deprecated...
> alias Foo Year;
> alias Foo Month;
> alias Foo Day;
>
>
> void bar( Year y, Month m, Day d ) {
> // ...
> }
>
> // This should compile, obviously.
> bar( Year(2010), Month(8), Day(14) );
>
> // But this shouldn't
> bar( Day(1), Year(1), Month(1) );
> ---
>
> So, what options do I have? I know that typedef is scheduled to
> deprecation, so I would like to know if there's something else.
>
>

August 15, 2010
On Saturday 14 August 2010 18:15:40 Yao G. wrote:
> On Sat, 14 Aug 2010 20:05:04 -0500, Jonathan M Davis
> 
> <jmdavisprog@gmail.com> wrote:
> > [snip]
> > 
> > Are you looking to create a new type that while technically identical to another type is not considered the same as that type by the type system?
> > 
> > - Jonathan M Davis
> 
> Yes, This is exactly what I want. I need, for example, that if you pass a Year instance to the Month parameter, generate a compiler error.

Well, if you search the D list for typedef, you should find some posts that suggest templated structs combined with alias which get you typedefs. It sounds like something like that will probably end up in Phobos at some point, though apparently there are some issues with conversions (though what they would be if you're trying to keep the types completely separate, I don't know).

- Jonathan M Davis
August 15, 2010
On Sat, 14 Aug 2010 20:28:56 -0500, sybrandy <sybrandy@gmail.com> wrote:

> I can't recall if you can do this with structs, but if you use classes, you should be able to define a "Date Part" class that has all of the methods and data you want.  Then, you just derive three sub-classes.
>
> For example (and I hope the syntax is right):
>
> class DatePart
> {
>     this(int f)
>     {
>        _foo = f;
>     }
>
>     int asNumber() { return _foo; }
>
>     immutable int _foo;
> }
>
> class Year: DatePart {}
>
> class Month: DatePart {}
>
> class Day: DatePart {}
>
> Casey

Yes. Unfortunately, I need to use structs because the types that I'm defining are value types. But thanks for the answer


-- 
Yao G.
August 15, 2010
On Sat, 14 Aug 2010 20:34:02 -0500, Jonathan M Davis <jmdavisprog@gmail.com> wrote:

> Well, if you search the D list for typedef, you should find some posts that
> suggest templated structs combined with alias which get you typedefs. It sounds
> like something like that will probably end up in Phobos at some point, though
> apparently there are some issues with conversions (though what they would be if
> you're trying to keep the types completely separate, I don't know).
>
> - Jonathan M Davis

Indeed. I did a search on the news group and found this code in a Trass3r post:

> enum Type
> {
>      Independent,
>      Super,
>      Sub,
>      Parallel,
> }
>
> struct Typedef( T, Type type = Type.Sub, T init = T.init, string _f = __FILE__, int _l = __LINE__ )
> {
>      T payload = init;
>
>      static if ( type != Type.Independent )
>      {
>          this( T value )
>          {
>              payload = value;
>          }
>      }
>      static if ( type == Type.Sub || type == Type.Parallel )
>      {
>          alias payload this;
>      }
>      static if ( type == Type.Super )
>      {
>          typeof( this ) opAssign( T value )
>          {
>              payload = value;
>              return this;
>          }
>      }
>      else static if ( type == Type.Sub )
>      {
>          @disable void opAssign( T value );
>      }
> }

I think I'll do something similar as this. I don't need either explicit or implicit cast between types.


-- 
Yao G.
August 15, 2010
I settled this just using an enum value passed as template argument:

---
enum DatePart
{
    Year,
    Month,
    Day,
}

struct DatePartImpl(T : DatePart )
{
    // Insert implementation here...
}

alias DatePartImpl!(DatePart.Year)  Year;
alias DatePartImpl!(DatePart.Month) Month;
alias DatePartImpl!(DatePart.Day)   Day;

void foo( Year y, Month m, Day d ) {}

// Works correctly
foo( Year(2010), Month(8), Day(14) );

// But this isn't allowed
foo( Day(14), Year(2010), Month(8) );
---


-- 
Yao G.