Testing implicit conversion to template instance with is() expression

2015-03-15 Thread via Digitalmars-d-learn

Should this work?

struct V(string s) {
}

struct S(int U) {
V!xyz x;
alias x this;
}

void main() {
S!10 a;
static assert(is(a : V!Args, Args...));
}

With DMD Git master, the static assert() fails. Should it? Am I 
doing something wrong? How can I test whether something is 
implicitly convertible to any instance of a particular template?


Re: Testing implicit conversion to template instance with is() expression

2015-03-15 Thread Ali Çehreli via Digitalmars-d-learn
On 03/15/2015 08:47 AM, Marc =?UTF-8?B?U2Now7x0eiI=?= 
schue...@gmx.net wrote:


 Should this work?

  struct V(string s) {
  }

  struct S(int U) {
  V!xyz x;
  alias x this;
  }

  void main() {
  S!10 a;
  static assert(is(a : V!Args, Args...));
  }

 With DMD Git master, the static assert() fails. Should it? Am I doing
 something wrong? How can I test whether something is implicitly
 convertible to any instance of a particular template?

There is no way other than checking for compile-time duck typing (see 
the implementations of isInputRange and others).


One reason is that the compiler does not have the concept of an 
instance of a template. Templates are for code generation and only the 
end-result (i.e. S!10) lives as a concept when compiling.


Ali



Re: Testing implicit conversion to template instance with is() expression

2015-03-15 Thread via Digitalmars-d-learn

On Sunday, 15 March 2015 at 16:44:14 UTC, Ali Çehreli wrote:
On 03/15/2015 08:47 AM, Marc =?UTF-8?B?U2Now7x0eiI=?= 
schue...@gmx.net wrote:


 Should this work?

  struct V(string s) {
  }

  struct S(int U) {
  V!xyz x;
  alias x this;
  }

  void main() {
  S!10 a;
  static assert(is(a : V!Args, Args...));
  }

 With DMD Git master, the static assert() fails. Should it? Am
I doing
 something wrong? How can I test whether something is
implicitly
 convertible to any instance of a particular template?

There is no way other than checking for compile-time duck 
typing (see the implementations of isInputRange and others).


One reason is that the compiler does not have the concept of 
an instance of a template. Templates are for code generation 
and only the end-result (i.e. S!10) lives as a concept when 
compiling.


The code contained a small mistake, I forgot a `typeof()`:

// static assert(is(a : V!Args, Args...));
// should be:
static assert(is(typeof(a) : V!Args, Args...));

This still fails, but it works when I change it to:

static assert(is(typeof(a) : S!Args, Args...));

This means I can indeed test whether something _is_ an instance 
of a template. It just doesn't take the `alias this` into 
account. So I guess that's a bug?


Re: Testing implicit conversion to template instance with is() expression

2015-03-15 Thread via Digitalmars-d-learn

https://issues.dlang.org/show_bug.cgi?id=14286

In the meantime, does someone know of a suitable workaround?


Re: Testing implicit conversion to template instance with is() expression

2015-03-15 Thread via Digitalmars-d-learn

On Sunday, 15 March 2015 at 16:53:34 UTC, Marc Schütz wrote:

On Sunday, 15 March 2015 at 16:44:14 UTC, Ali Çehreli wrote:
On 03/15/2015 08:47 AM, Marc =?UTF-8?B?U2Now7x0eiI=?= 
schue...@gmx.net wrote:


 Should this work?

 struct V(string s) {
 }

 struct S(int U) {
 V!xyz x;
 alias x this;
 }

 void main() {
 S!10 a;
 static assert(is(a : V!Args, Args...));
 }

 With DMD Git master, the static assert() fails. Should it? Am
I doing
 something wrong? How can I test whether something is
implicitly
 convertible to any instance of a particular template?

There is no way other than checking for compile-time duck 
typing (see the implementations of isInputRange and others).


One reason is that the compiler does not have the concept of 
an instance of a template. Templates are for code generation 
and only the end-result (i.e. S!10) lives as a concept when 
compiling.


The code contained a small mistake, I forgot a `typeof()`:

// static assert(is(a : V!Args, Args...));
// should be:
static assert(is(typeof(a) : V!Args, Args...));

This still fails, but it works when I change it to:

static assert(is(typeof(a) : S!Args, Args...));

This means I can indeed test whether something _is_ an instance 
of a template. It just doesn't take the `alias this` into 
account. So I guess that's a bug?


Ok, now I'm pretty sure:

class V(string s) {
}

class S(int U) : V!xyz {
}

void main() {
S!10 a;
static if(is(typeof(a) : V!Args, Args...))
pragma(msg, Args);
}

This works, and it even correctly infers `Args` to be 
`tuple(xyz)`. As `alias this` is supposed to be interchangeable 
with subtyping, it must be a bug.


Re: Testing implicit conversion to template instance with is() expression

2015-03-15 Thread via Digitalmars-d-learn

On Sunday, 15 March 2015 at 18:53:33 UTC, Nicolas Sicard wrote:

Can be reduced to:
struct Foo(int i) {}
alias Foo1 = Foo!1;
static assert(is(Foo!2 == Foo1!T, T...)); // OK

I think it's another bug.


Right, I've filed another report:
https://issues.dlang.org/show_bug.cgi?id=14290


Re: Testing implicit conversion to template instance with is() expression

2015-03-15 Thread via Digitalmars-d-learn

On Sunday, 15 March 2015 at 17:03:42 UTC, Marc Schütz wrote:

https://issues.dlang.org/show_bug.cgi?id=14286

In the meantime, does someone know of a suitable workaround?


I found the following workaround. Not beautiful, but it works:

enum isValue(alias T) = __traits(compiles, typeof(T));

template isConvertibleToInstanceOf(alias From, alias To)
if(isValue!From)
{
enum isConvertibleToInstanceOf = 
isConvertibleToInstanceOf!(typeof(From), To);

}

template isConvertibleToInstanceOf(From, alias To)
if(!is(From == struct)  !is(From == class)  !is(From == 
interface))

{
enum isConvertibleToInstanceOf = false;
}

template isConvertibleToInstanceOf(From, alias To)
if(is(From == struct) || is(From == class) || is(From == 
interface))

{
// workaround for 
https://issues.dlang.org/show_bug.cgi?id=14286

import std.typetuple : anySatisfy;
enum aliasThisConvertible(string name) = 
isConvertibleToInstanceOf!(mixin(typeof(From. ~ name ~ )), 
To);

enum isConvertibleToInstanceOf =
anySatisfy!(aliasThisConvertible, 
__traits(getAliasThis, From)) ||

is(From : To!Args, Args...);
}


Re: Testing implicit conversion to template instance with is() expression

2015-03-15 Thread Nicolas Sicard via Digitalmars-d-learn

On Sunday, 15 March 2015 at 18:33:32 UTC, Marc Schütz wrote:

On Sunday, 15 March 2015 at 17:03:42 UTC, Marc Schütz wrote:

https://issues.dlang.org/show_bug.cgi?id=14286

In the meantime, does someone know of a suitable workaround?


I found the following workaround. Not beautiful, but it works:

enum isValue(alias T) = __traits(compiles, typeof(T));

template isConvertibleToInstanceOf(alias From, alias To)
if(isValue!From)
{
enum isConvertibleToInstanceOf = 
isConvertibleToInstanceOf!(typeof(From), To);

}

template isConvertibleToInstanceOf(From, alias To)
if(!is(From == struct)  !is(From == class)  !is(From == 
interface))

{
enum isConvertibleToInstanceOf = false;
}

template isConvertibleToInstanceOf(From, alias To)
if(is(From == struct) || is(From == class) || is(From == 
interface))

{
// workaround for 
https://issues.dlang.org/show_bug.cgi?id=14286

import std.typetuple : anySatisfy;
enum aliasThisConvertible(string name) = 
isConvertibleToInstanceOf!(mixin(typeof(From. ~ name ~ )), 
To);

enum isConvertibleToInstanceOf =
anySatisfy!(aliasThisConvertible, 
__traits(getAliasThis, From)) ||

is(From : To!Args, Args...);
}


It works for your previous code example:
static assert(isConvertibleToInstanceOf!(S!10, V)); // OK

But this also works:
static assert(!isConvertibleToInstanceOf!(S!10, V!abc)); // OK

Can be reduced to:
struct Foo(int i) {}
alias Foo1 = Foo!1;
static assert(is(Foo!2 == Foo1!T, T...)); // OK

I think it's another bug.