Thread overview | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 30, 2021 Derived type | ||||
---|---|---|---|---|
| ||||
Hello. When i adapt C code, i see new type creation: typedef void* Xobj; Or code like this: struct _Xobj; typedef struct _Xobj *Xobj; I want create derived type in D, found std.typecons.Typedef template, and write: alias Xobj = Typedef!(void*, (void*).init); But compiler use long type name in error messages, like this: Error: function test6.foo(Typedef!(void*, null, null) obj) is not callable using argument types (void*) cannot pass argument bad of type void* to parameter Typedef!(void*, null, null) obj This messages dont help me understand, which type should i use. What i should change? Or Typedef template should be changes? Any Typedef alternatives? |
March 30, 2021 Re: Derived type | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice3 | On Tuesday, 30 March 2021 at 13:28:55 UTC, novice3 wrote: > > This messages dont help me understand, which type should i use. > What i should change? > Or Typedef template should be changes? From the docs: "Unlike the alias feature, Typedef ensures the two types are not considered as equals. Parameters:" https://dlang.org/phobos/std_typecons.html#Typedef > Any Typedef alternatives? If you want your new type to be interchangeable with another, the straightforward way is just to use an alias. Buf if you need a more concrete type, you can use alias this in a struct: import std.stdio; struct MyType { void* wrapped; alias wrapped this; } void doSomething(void* t) { writeln(*(cast(int*)t)); } void main() { int i = 20; MyType mt = MyType(&i); doSomething(mt); } |
March 30, 2021 Re: Derived type | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice3 | On Tuesday, 30 March 2021 at 13:28:55 UTC, novice3 wrote:
> Hello.
>
> When i adapt C code, i see new type creation:
> typedef void* Xobj;
>
> Or code like this:
> struct _Xobj;
> typedef struct _Xobj *Xobj;
>
>
> I want create derived type in D, found std.typecons.Typedef template, and write:
> alias Xobj = Typedef!(void*, (void*).init);
>
> But compiler use long type name in error messages, like this:
>
> Error: function test6.foo(Typedef!(void*, null, null) obj) is not callable using argument types (void*)
>
> cannot pass argument bad of type void* to parameter Typedef!(void*, null, null) obj
>
> This messages dont help me understand, which type should i use.
> What i should change?
> Or Typedef template should be changes?
> Any Typedef alternatives?
The typedef in C in D is just an alias:
```
alias Xobj = void*;
```
Xobj can then be used interchangeably with void*, so all void* arguments accept Xobj and all Xobj arguments accept void*.
If you want a type-safe alias that makes all void* arguments accept Xobj but not Xobj arguments to accept void* you can use `Typedef` like you linked. However using this language built-in feature is much simpler and cheaper in terms of resource usage and compile time + always results in the fastest code: (there is no conversions at all)
```
enum Xobj : void*;
```
This allows explicit conversion in both ways using cast, but only allows implicit conversion from Xobj to void*, not from void* to Xobj:
```
void* x = someValue;
Xobj y = cast(Xobj)x; // ok
x = y; // ok
y = x; // error (need explicit cast)
```
|
March 30, 2021 Re: Derived type | ||||
---|---|---|---|---|
| ||||
Posted in reply to WebFreak001 | On Tuesday, 30 March 2021 at 14:45:12 UTC, WebFreak001 wrote: >> When i adapt C code, i see new type creation: > The typedef in C in D is just an alias: > > ``` > alias Xobj = void*; > ``` I totally overlooked the part about porting from C. Yes, this is the way to go in that case. |
March 30, 2021 Re: Derived type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Tuesday, 30 March 2021 at 13:43:52 UTC, Mike Parker wrote: > the straightforward way is just to use an alias. i cant use alias - compiler cannot distinguish base type and alias, and cannot catch programmer errors > Buf if you need a more concrete type, you can use alias this in a struct: I think Typedef template should do this struct for me. Thanks Mike, this way is what i wanted struct Xobj { private void* payload; alias payload this; } Xobj good; foo(good); //nice foo(cast(Xobj)null); //explicit cast allowed - nice foo(null); //no implicit cast disallowed - compiler error - nice void* bad; foo(bad); //compiler distinguish type - error - nice I think Typedef template should do this struct for me. Problem with Typedef template - code alias Xobj = Typedef!(void*) not generate struct named "Xobj", but struct named "Typedef!(void*, null, null)". This makes compiler error messages unusable. I will try to make template for struct. But template is black magic for me :) |
March 30, 2021 Re: Derived type | ||||
---|---|---|---|---|
| ||||
Posted in reply to WebFreak001 | On Tuesday, 30 March 2021 at 14:45:12 UTC, WebFreak001 wrote: > Xobj can then be used interchangeably with void*, so all void* arguments accept Xobj and all Xobj arguments accept void*. yes, i understand alias, and i dont want such behaviour > If you want a type-safe alias that makes all void* arguments accept Xobj but not Xobj arguments to accept void* yes, this is that i search > you can use `Typedef` like you linked. Problem with Typedef template - code alias Xobj = Typedef!(void*) not generate type named "Xobj", but type named "Typedef!(void*, null, null)". This makes compiler error messages unusable. > enum Xobj : void*; > ``` > This allows explicit conversion in both ways using cast, but only allows implicit conversion from Xobj to void*, not from void* to Xobj: Strange syntax. Behavour exactly what i want, but this code not works for me :( enum Xobj : void*; Xobj var; //DMD Error: enum test7.Xobj forward reference of Xobj.init |
March 30, 2021 Re: Derived type | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice3 | On 3/30/21 6:28 AM, novice3 wrote: > I want create derived type in D "Derived type" is used in the context of object oriented programming at least in D but your examples indicate you need something else. How about the 'alias this' feature? import std.stdio; struct Xobj { void* value; alias value this; } void main() { int i; auto var = Xobj(&i); writeln(var); int j; var = &j; } alias this is for implicit conversions, from Xobj to void* in this case. Ali |
March 30, 2021 Re: Derived type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Tuesday, 30 March 2021 at 19:12:29 UTC, Ali Çehreli wrote: > "Derived type" is used in the context of object oriented programming at least in D Sorry, i use wrong termin. I just want create new type Tnew, based on exist type Tbase. Tnew have same allowed values, same properties, same allowed operations as Tbase. Compiler should distinguish New from Tbase. Allowed implicit cast Tnew to Tbase. Prohibited implicit cast Tbase to Tnew. Allowed exlicit cast Tbase to Tnew. > but your examples indicate you need something else. How about the 'alias this' feature? Thanks, this is what i want. I just think that Typedef do it for me, hide this boilerplait code. |
March 30, 2021 Re: Derived type | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice2 | My tries to make template for struct and alias this: ////// variant 1 template Typedef(alias Tnew, Tbase) { struct Tnew { Tbase payload; alias payload this; } } Typedef!(Xobj, void*); void foo (Xobj obj) {} //compiler Error: no identifier for declarator Typedef!(Xobj, void*) ////// variant 2 mixin template Typedef(alias Tnew, Tbase) { struct Tnew { Tbase payload; alias payload this; } } mixin Typedef!(Xobj, void*); //compiler Error: undefined identifier Xobj |
March 30, 2021 Re: Derived type | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice2 | On Tuesday, 30 March 2021 at 19:47:41 UTC, novice2 wrote: > My tries to make template for struct and alias this: > > ////// variant 1 > template Typedef(alias Tnew, Tbase) > { > struct Tnew > { > Tbase payload; > alias payload this; > } > } > you must give a name to the template specialization, using alias [1], also the TypeDef declaration can be highly simplified: --- struct Typedef(TBase) { TBase payload; alias payload this; } alias Xobj = Typedef!(void*); void foo (Xobj obj) {} --- [1]: https://dlang.org/spec/declaration.html#alias |
Copyright © 1999-2021 by the D Language Foundation