Jump to page: 1 2
Thread overview
How can I test at compile time whether T is an instance of an interface ?
Sep 23, 2020
wjoe
Sep 23, 2020
data pulverizer
Sep 23, 2020
wjoe
Sep 23, 2020
data pulverizer
Sep 23, 2020
H. S. Teoh
Sep 23, 2020
data pulverizer
Sep 23, 2020
data pulverizer
Sep 23, 2020
data pulverizer
Sep 24, 2020
data pulverizer
Sep 23, 2020
wjoe
Sep 23, 2020
data pulverizer
Sep 23, 2020
H. S. Teoh
Sep 23, 2020
wjoe
Sep 24, 2020
Otávio Augusto
September 23, 2020
I have some similar functions:

void register(C: IFoo)()
{
  _insert!C();
}

void register(C)() if (behavesLikeFoo!C)
{
  _insert!C();
}

There are more overloads with parameters so I want to merge them

void register(C, ARGS...)(ARGS args) if (behavesLikeFoo!C || isInstanceOf!(C, IFoo))
{
  _insert!C(args);
}

I found a lot of information on how to do this at runtime but not at compile time.
std.traits: isInstanceOf doesn't work. Neither did anything I tried with typeid etc.

The behavesLikeFoo constraint works as expected but it accepts any class no matter whether or not it implements the interface.
September 23, 2020
On Wednesday, 23 September 2020 at 18:37:45 UTC, wjoe wrote:
> I have some similar functions:
>
> void register(C: IFoo)()
> {
>   _insert!C();
> }
>
> void register(C)() if (behavesLikeFoo!C)
> {
>   _insert!C();
> }
>
> There are more overloads with parameters so I want to merge them
>
> void register(C, ARGS...)(ARGS args) if (behavesLikeFoo!C || isInstanceOf!(C, IFoo))
> {
>   _insert!C(args);
> }
>
> I found a lot of information on how to do this at runtime but not at compile time.
> std.traits: isInstanceOf doesn't work. Neither did anything I tried with typeid etc.
>
> The behavesLikeFoo constraint works as expected but it accepts any class no matter whether or not it implements the interface.

A class at compile time is it's own static type, OOP polymorphism is a runtime feature not compile time. You have to write your own traits for specific objects to get them to relate to each other using static overloading.
September 23, 2020
Try this:

	interface I {}
	class C : I {}
	class D {}
	struct S {}

	pragma(msg, is(C : I));	// true
	pragma(msg, is(D : I));	// false
	pragma(msg, is(S : I));	// false

So probably what you want is something like this:

	void register(C, ARGS...)(ARGS args)
		if (behavesLikeFoo!C || is(C : IFoo))
		...


T

-- 
Change is inevitable, except from a vending machine.
September 23, 2020
On Wednesday, 23 September 2020 at 18:49:28 UTC, data pulverizer wrote:
> On Wednesday, 23 September 2020 at 18:37:45 UTC, wjoe wrote:
>> [...]
>
> A class at compile time is it's own static type, OOP polymorphism is a runtime feature not compile time. You have to write your own traits for specific objects to get them to relate to each other using static overloading.

It doesn't occur to me that the compiler doesn't know at compile time that

interface IFoo{}
class Foo: IFoo {}

class Foo implements interface IFoo.

September 23, 2020
On Wednesday, 23 September 2020 at 18:50:28 UTC, H. S. Teoh wrote:
> Try this:
>
> 	interface I {}
> 	class C : I {}
> 	class D {}
> 	struct S {}
>
> 	pragma(msg, is(C : I));	// true
> 	pragma(msg, is(D : I));	// false
> 	pragma(msg, is(S : I));	// false
>
> So probably what you want is something like this:
>
> 	void register(C, ARGS...)(ARGS args)
> 		if (behavesLikeFoo!C || is(C : IFoo))
> 		...
>
>
> T

Yes, that's it. Thanks :)
September 23, 2020
On Wednesday, 23 September 2020 at 18:56:33 UTC, wjoe wrote:
>
> It doesn't occur to me that the compiler doesn't know at compile time that
>
> interface IFoo{}
> class Foo: IFoo {}
>
> class Foo implements interface IFoo.

Didn't think that the compiler didn't know but wasn't aware that you could use that information to statically dispatch. My mistake, I'll shut up now!


September 23, 2020
On Wed, Sep 23, 2020 at 07:08:47PM +0000, data pulverizer via Digitalmars-d-learn wrote:
> On Wednesday, 23 September 2020 at 18:56:33 UTC, wjoe wrote:
> > 
> > It doesn't occur to me that the compiler doesn't know at compile time that
> > 
> > interface IFoo{}
> > class Foo: IFoo {}
> > 
> > class Foo implements interface IFoo.
> 
> Didn't think that the compiler didn't know but wasn't aware that you could use that information to statically dispatch. My mistake, I'll shut up now!

Of course the compiler knows. And of course it can use this information for static dispatch. That's why D is so awesome at metaprogramming. ;-)

What the compiler *doesn't* know is whether a variable of some supertype of Foo (say Object) implements IFoo, because that's something that can only be determined at runtime (effectively, you need to downcast to Foo / IFoo and test if it's null).  But that's not what the OP is asking for in this case.


T

-- 
Error: Keyboard not attached. Press F1 to continue. -- Yoon Ha Lee, CONLANG
September 23, 2020
On Wednesday, 23 September 2020 at 19:08:47 UTC, data pulverizer wrote:
> On Wednesday, 23 September 2020 at 18:56:33 UTC, wjoe wrote:
>> [...]
>
> Didn't think that the compiler didn't know but wasn't aware that you could use that information to statically dispatch. My mistake, I'll shut up now!

Appologies if you took offense. Your replies are very much appreciated.
September 23, 2020
On Wednesday, 23 September 2020 at 19:16:13 UTC, H. S. Teoh wrote:
>
> Of course the compiler knows. And of course it can use this information for static dispatch. That's why D is so awesome at metaprogramming. ;-)
>
> What the compiler *doesn't* know is whether a variable of some supertype of Foo (say Object) implements IFoo, because that's something that can only be determined at runtime (effectively, you need to downcast to Foo / IFoo and test if it's null).  But that's not what the OP is asking for in this case.
>
>
> T

This has prompted me to write a data structure that I thought would be impossible until now. It's a data structure with a Start node with a link to next, then any number of Middle nodes with previous and next links, and an End node with a previous link all inheriting from a common interface Node. This is of course possible using runtime polymorphism, but I wanted it available for static dispatch rather than everything being listed as "Node" static type. The implementation is below and works.

Interestingly when I wrote it down with a pen and paper I thought that it would lead to infinitely recursive unwriteable data type and so didn't even bother trying to implement it. But D actually forms the correct static type, it prints the gobbledygook type I expect at compile time but the actual static type at runtime. Amazing! I have been using structs with tuples because I thought this data structure was impossible!

```
import std.stdio: writeln;

interface Node{}
class Start: Node
{
  Node next;
}
class Middle: Node
{
  Node prev;
  Node next;
}
class End: Node
{
  Node prev;
}

auto makeChain(Args...)(Args args)
if(Args.length > 3)
{
  args[0].next = args[1];
  static foreach(i; 1..(Args.length - 1))
  {
    args[i].prev = args[i - 1];
    args[i].next = args[i + 1];
  }
  args[$ - 1].prev = args[$ - 2];
  return args[0];
}

void main()
{
  static const x = makeChain(new Start(), new Middle(), new Middle(),
                                  new Middle(), new Middle(), new End());
  pragma(msg, "x.next: ", x.next, "\n");
  writeln("x.next: ", x.next);
}
```

output:

```
x.next: Middle(Start(Middle(<recursion>)), Middle(Middle(Start(Middle(<recursion>)), Middle(<recursion>)), Middle(Middle(Middle(Start(Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), Middle(Middle(Middle(Middle(Start(Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), End(Middle(Middle(Middle(Middle(Start(Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), Middle(<recursion>)), End(<recursion>)))))))

x.next: node.Middle
```

September 23, 2020
On Wednesday, 23 September 2020 at 19:27:13 UTC, wjoe wrote:
> Appologies if you took offense. Your replies are very much appreciated.

No offense taken.
« First   ‹ Prev
1 2