Jump to page: 1 2
Thread overview
using a typedefed variable with library classes
Jan 10, 2009
Charles Hixson
Jan 10, 2009
Bill Baxter
Jan 11, 2009
Charles Hixson
Jan 11, 2009
bearophile
Jan 11, 2009
Bill Baxter
Jan 11, 2009
bearophile
Jan 12, 2009
Charles Hixson
Jan 12, 2009
Sergey Gromov
Jan 12, 2009
Bill Baxter
Jan 12, 2009
Sergey Gromov
Jan 15, 2009
Charles Hixson
Jan 16, 2009
Christopher Wright
Jan 18, 2009
Charles Hixson
Jan 18, 2009
Christopher Wright
Jan 18, 2009
Christopher Wright
Jan 18, 2009
Christopher Wright
January 10, 2009
Is it possible to use a typedefed variable with library classes?

In particular, what I've done is:

typedef  int  TestType;
TestType  t;
File      f;

t = 42;
f.write (t);

And the response I get is the compiler asking whether I want to write bytes or a long.

Am I doing something grossly wrong?  Or is typedef just broken?  Or is it really supposed to work that way for some not-understood reason?
(alias works fine...but this seems to make typedef basically useless. Unless there's a way of adding functions to the library classes [like file] so that they'll understand how to cast the typedefed variable.)
January 10, 2009
On Sun, Jan 11, 2009 at 8:23 AM, Charles Hixson <charleshixsn@earthlink.net> wrote:
> Is it possible to use a typedefed variable with library classes?
>
> In particular, what I've done is:
>
> typedef  int  TestType;
> TestType  t;
> File      f;
>
> t = 42;
> f.write (t);
>
> And the response I get is the compiler asking whether I want to write bytes or a long.
>
> Am I doing something grossly wrong?  Or is typedef just broken?  Or is it
> really supposed to work that way for some not-understood reason?
> (alias works fine...but this seems to make typedef basically useless. Unless
> there's a way of adding functions to the library classes [like file] so that
> they'll understand how to cast the typedefed variable.)
>

I've never found a use for typedef myself.  I don't think it's used much, so it could be that it's a special case that Andrei didn't consider when re-writing write()  [at least I'm assuming you're talking D2, based on the error message].  Or it could be that it is a bug with the compiler.  But either way I think no one uses it, so it's likely to flush out lots of corner cases.

--bb
January 11, 2009
Bill Baxter wrote:
> On Sun, Jan 11, 2009 at 8:23 AM, Charles Hixson
> <charleshixsn@earthlink.net> wrote:
>> Is it possible to use a typedefed variable with library classes?
>>
>> In particular, what I've done is:
>>
>> typedef  int  TestType;
>> TestType  t;
>> File      f;
>>
>> t = 42;
>> f.write (t);
>>
>> And the response I get is the compiler asking whether I want to write bytes
>> or a long.
>>
>> Am I doing something grossly wrong?  Or is typedef just broken?  Or is it
>> really supposed to work that way for some not-understood reason?
>> (alias works fine...but this seems to make typedef basically useless. Unless
>> there's a way of adding functions to the library classes [like file] so that
>> they'll understand how to cast the typedefed variable.)
>>
> 
> I've never found a use for typedef myself.  I don't think it's used
> much, so it could be that it's a special case that Andrei didn't
> consider when re-writing write()  [at least I'm assuming you're
> talking D2, based on the error message].  Or it could be that it is a
> bug with the compiler.  But either way I think no one uses it, so it's
> likely to flush out lots of corner cases.
> 
> --bb
Sorry.  Yes, it was D2.  Guess I'll just avoid it then. (Pity.)
January 11, 2009
Bill Baxter:
> I've never found a use for typedef myself.  I don't think it's used much,<

In Pascal (and its variant and children, like ObjectPascals, etc) there is a section named Type where you define your typedefs. People used to program in Pascal-like languages (ObjectPascals, Ada, Oberon, etc) may appreciate the typedef of D and they may use it.
I use typedef now and then, I presume it's mostly useful for imperative style of programming and not much in OOP.

A simple usage example: you have a procedural/functional program that has several functions that process a matrix, the same matrix, for example a float[12][7]. In such situation you may want to define:

typedef float[12][7] FPfield;

Then if you use FPField in function signatures like this:
void foo(FPfield mat, ...) { ... }
you gain some things:
- The type name may be shorter, saving you some typing. And you don't need to remember each time the size of the dimensions.
- If you later want to FPfield into a matrix of doubles or the matrix you have to change only one line. If your code uses a dynamic array this is less important. But from coding a lot of programs in D I have seen programs up to 2-5-10 times faster when I use 3D/4D static arrays, mostly because lot of address computations are done at compile time or partially optimized away instead of run time, and because of higher cache coherence. I can show an extreme example, if you want. D dynamic arrays can't replace all static arrays where speed matters.
- It's a way to document the code, because you aren't just giving a generic matrix to foo, you are giving it a FPfield, this often has an important semantic meaning.
- It's type safe, so you don't risk giving the wrong matrix to foo. You can't do this well with an alias. This is more useful in largish programs.

If you use OOP or lot generic programming this becomes less important.

Bye,
bearophile
January 11, 2009
On Sun, Jan 11, 2009 at 10:16 AM, bearophile <bearophileHUGS@lycos.com> wrote:
> Bill Baxter:
>> I've never found a use for typedef myself.  I don't think it's used much,<
>
> In Pascal (and its variant and children, like ObjectPascals, etc) there is a section named Type where you define your typedefs. People used to program in Pascal-like languages (ObjectPascals, Ada, Oberon, etc) may appreciate the typedef of D and they may use it.
> I use typedef now and then, I presume it's mostly useful for imperative style of programming and not much in OOP.
>
> A simple usage example: you have a procedural/functional program that has several functions that process a matrix, the same matrix, for example a float[12][7]. In such situation you may want to define:
>
> typedef float[12][7] FPfield;
>
> Then if you use FPField in function signatures like this:
> void foo(FPfield mat, ...) { ... }
> you gain some things:
> - The type name may be shorter, saving you some typing. And you don't need to remember each time the size of the dimensions.
> - If you later want to FPfield into a matrix of doubles or the matrix you have to change only one line. If your code uses a dynamic array this is less important. But from coding a lot of programs in D I have seen programs up to 2-5-10 times faster when I use 3D/4D static arrays, mostly because lot of address computations are done at compile time or partially optimized away instead of run time, and because of higher cache coherence. I can show an extreme example, if you want. D dynamic arrays can't replace all static arrays where speed matters.
> - It's a way to document the code, because you aren't just giving a generic matrix to foo, you are giving it a FPfield, this often has an important semantic meaning.
> - It's type safe, so you don't risk giving the wrong matrix to foo. You can't do this well with an alias. This is more useful in largish programs.
>
> If you use OOP or lot generic programming this becomes less important.


Actually it might be useful to me.  The first time I tried to use it
my thought was to do
  typedef Exception MyException;

To create a different exception type.  That doesn't work so I kinda just said, eh whatever, this typedef stuff doesn't work yet.

But probably that's just because that's not the use case they were intended for.

Something I might be able to use it for is for index types.  Like this:

typedef size_t VertexHandle;
typedef size_t FaceHandle;

Now I can't accidentally assign a vertex handle to a face handle. That could be useful.

--bb
January 11, 2009
Bill Baxter:

> The first time I tried to use it my thought was to do
>   typedef Exception MyException;
> To create a different exception type.  That doesn't work so I kinda
> just said, eh whatever, this typedef stuff doesn't work yet.

You are right, typedef was invented before classes and OOP, so what you say doesn't work :-)
But I think typedef may be modified to work as you want too, that is to define a subtype (so the runtime typeinfo of MyException too has to be different!). I/we can ask Walter what he thinks about this.


> Now I can't accidentally assign a vertex handle to a face handle. That could be useful.

Right. But so far I don't see problems in extending the semantics of typedef to work with OOP too. Maybe other people here can spot a problem. I presume Walter doesn't read this newsgroup, so I can post a summary in the main D group too, later.

Bye,
bearophile
January 12, 2009
bearophile wrote:
> Bill Baxter:
> 
>> The first time I tried to use it my thought was to do
>>   typedef Exception MyException;
>> To create a different exception type.  That doesn't work so I kinda
>> just said, eh whatever, this typedef stuff doesn't work yet.
> 
> You are right, typedef was invented before classes and OOP, so what you say doesn't work :-)
> But I think typedef may be modified to work as you want too, that is to define a subtype (so the runtime typeinfo of MyException too has to be different!). I/we can ask Walter what he thinks about this.
> 
> 
>> Now I can't accidentally assign a vertex handle to a face handle.
>> That could be useful.
> 
> Right. But so far I don't see problems in extending the semantics of typedef to work with OOP too. Maybe other people here can spot a problem. I presume Walter doesn't read this newsgroup, so I can post a summary in the main D group too, later.
> 
> Bye,
> bearophile
Well, my use case just involves being able to use library function with the proper base type.  (I.e., int instead of long or byte when I do
typedef int LocalType;
LocalType t;
File f;
f.write(t);

I'll grant that I *can* use alias for such a purpose, but that doesn't distinguish between LocalType and ArrayIndex in routines defined for those types.  E.g.:
typedef  int ArrayIndex;
void zeroIndex(out ArrayIndex ai)  {	ai = 0;  }
zeroIndex(t);

Should throw an error.  If I'm using alias it doesn't (and shouldn't);
January 12, 2009
Sun, 11 Jan 2009 18:09:15 -0800, Charles Hixson wrote:

> Well, my use case just involves being able to use library function with
> the proper base type.  (I.e., int instead of long or byte when I do
> typedef int LocalType;
> LocalType t;
> File f;
> f.write(t);
> 
> I'll grant that I *can* use alias for such a purpose, but that doesn't
> distinguish between LocalType and ArrayIndex in routines defined for
> those types.  E.g.:
> typedef  int ArrayIndex;
> void zeroIndex(out ArrayIndex ai)  {	ai = 0;  }
> zeroIndex(t);
> 
> Should throw an error.  If I'm using alias it doesn't (and shouldn't);

Well, I presume File.write() has many overloads, including one for int
but none for LocalType.  When aliasing, the LocalType *is* an int, it
matches exactly File.write(int) and the compiler is happy.

However, with a typedef, LocalType is a distinct type.  Yes it casts to int implicitly, but likewise it casts implicitly to char, short and long.  So compiler gets a whole load of File.write() functions matching with conversions, and fails because of the ambiguity.

That's how the language works, and it's pretty consistent IMO.  What you can do is:

  f.write(cast(int)t);

or use templates to generalize:

  auto fileWrite(T : LocalType)(File f, T v)
  {
    return f.write(cast(int)v);
  }
  auto fileWrite(T)(File f, T v)
  {
    return f.write(v);
  }
  fileWrite(f, t); // OK
  fileWrite(f, 15); // OK

When we get generic function calls you'd be even able to write:

  void write(File f, LocalType l)
  {
    f.write(cast(int)l);
  }
  f.write(t); // OK, write(f, t) is called
January 12, 2009
On Tue, Jan 13, 2009 at 1:48 AM, Sergey Gromov <snake.scaly@gmail.com> wrote:

> However, with a typedef, LocalType is a distinct type.  Yes it casts to int implicitly, but likewise it casts implicitly to char, short and long.  So compiler gets a whole load of File.write() functions matching with conversions, and fails because of the ambiguity.
>
> That's how the language works, and it's pretty consistent IMO.  What you can do is:

But the difference is LocalType can be converted to int exactly in all cases.  Given a choice of int,char,short,etc.  clearly the conversion to int is best choice.  It may be consistent with other cases involving multiple legal conversions, but usually you don't have such a single clearly preferred conversion.   It seems to significantly reduce the utility of typedef.

--bb
January 12, 2009
Tue, 13 Jan 2009 05:59:58 +0900, Bill Baxter wrote:

> On Tue, Jan 13, 2009 at 1:48 AM, Sergey Gromov <snake.scaly@gmail.com> wrote:
> 
>> However, with a typedef, LocalType is a distinct type.  Yes it casts to int implicitly, but likewise it casts implicitly to char, short and long.  So compiler gets a whole load of File.write() functions matching with conversions, and fails because of the ambiguity.
>>
>> That's how the language works, and it's pretty consistent IMO.  What you can do is:
> 
> But the difference is LocalType can be converted to int exactly in all cases.  Given a choice of int,char,short,etc.  clearly the conversion to int is best choice.  It may be consistent with other cases involving multiple legal conversions, but usually you don't have such a single clearly preferred conversion.   It seems to significantly reduce the utility of typedef.

It's about overload resolution rules.  The specs say:

  The levels of matching are:
  * no match
  * match with implicit conversions
  * exact match

There is no notion of 'best' implicit conversion.
« First   ‹ Prev
1 2