Jump to page: 1 2
Thread overview
Derived type
Mar 30, 2021
novice3
Mar 30, 2021
Mike Parker
Mar 30, 2021
novice2
Mar 30, 2021
novice2
Mar 30, 2021
Basile B.
Mar 31, 2021
novice3
Mar 31, 2021
Basile B.
Mar 31, 2021
novice3
Mar 30, 2021
WebFreak001
Mar 30, 2021
Mike Parker
Mar 30, 2021
novice2
Apr 01, 2021
WebFreak001
Apr 01, 2021
novice3
Apr 01, 2021
novice2
Mar 30, 2021
Ali Çehreli
Mar 30, 2021
novice2
Mar 31, 2021
Mike Parker
March 30, 2021
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
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
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
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
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
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
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
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
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
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

« First   ‹ Prev
1 2