www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - __traits(compiles) and template instantiation

reply jmh530 <john.michael.hall gmail.com> writes:
I've been playing around with __traits and I find myself confused 
on one aspect. In the code below, I was testing whether some 
templates would compile given types. For the most part it works 
as I would expect.

I think I get why the third one works with foo!(int). My guess is 
that it assumed that U is the same as T and both are int. 
However, that wouldn't make sense with the last one where I use 
bar!(int). In that one it's basically ignoring the second 
template constraint. So I don't understand what's going on for 
that last line to compile. To confirm I wasn't crazy, I get an 
error with
alias bar_ = bar!(int);



import std.traits : isNumeric;
import std.range : isInputRange;

void foo(T, U)(T x, U y) if (isNumeric!T && isNumeric!U) { }

void bar(T, U)(T x, U y) if (isNumeric!T && isInputRange!U) { }

void main()
{
	assert(__traits(compiles, foo!(int, int)));	//I get this
	assert(!__traits(compiles, foo!(bool, bool)));	//I get this
	assert(__traits(compiles, foo!(int)));		//I think I get this
	assert(__traits(compiles, bar!(int, int[])));	//I get this
	assert(!__traits(compiles, bar!(int, int)));	//I get this
	assert(__traits(compiles, bar!(int)));		//I don't get this
}
Apr 07 2016
parent reply Alex Parrill <initrd.gz gmail.com> writes:
On Thursday, 7 April 2016 at 20:31:12 UTC, jmh530 wrote:
 I've been playing around with __traits and I find myself 
 confused on one aspect. In the code below, I was testing 
 whether some templates would compile given types. For the most 
 part it works as I would expect.

 I think I get why the third one works with foo!(int). My guess 
 is that it assumed that U is the same as T and both are int. 
 However, that wouldn't make sense with the last one where I use 
 bar!(int). In that one it's basically ignoring the second 
 template constraint. So I don't understand what's going on for 
 that last line to compile. To confirm I wasn't crazy, I get an 
 error with
 alias bar_ = bar!(int);



 import std.traits : isNumeric;
 import std.range : isInputRange;

 void foo(T, U)(T x, U y) if (isNumeric!T && isNumeric!U) { }

 void bar(T, U)(T x, U y) if (isNumeric!T && isInputRange!U) { }

 void main()
 {
 	assert(__traits(compiles, foo!(int, int)));	//I get this
 	assert(!__traits(compiles, foo!(bool, bool)));	//I get this
 	assert(__traits(compiles, foo!(int)));		//I think I get this
 	assert(__traits(compiles, bar!(int, int[])));	//I get this
 	assert(!__traits(compiles, bar!(int, int)));	//I get this
 	assert(__traits(compiles, bar!(int)));		//I don't get this
 }
Neither the third nor sixth lines should be true. alias wrongfoo = foo!int; /* Error: template instance foo!int does not match template declaration foo(T, U)(T x, U y) if (isNumeric!T && isNumeric!U) */ alias rightfoo = foo!(int, int); /* ok */ File a DMD bug. (Also, you can use static assert here to check the assertions at build-time instead of run-time)
Apr 07 2016
parent reply jkpl <jkpl nowhere.de> writes:
On Thursday, 7 April 2016 at 21:36:37 UTC, Alex Parrill wrote:
 On Thursday, 7 April 2016 at 20:31:12 UTC, jmh530 wrote:
 I've been playing around with __traits and I find myself 
 confused on one aspect. In the code below, I was testing 
 whether some templates would compile given types. For the most 
 part it works as I would expect.
 [...]
Neither the third nor sixth lines should be true. alias wrongfoo = foo!int; /* Error: template instance foo!int does not match template declaration foo(T, U)(T x, U y) if (isNumeric!T && isNumeric!U) */ alias rightfoo = foo!(int, int); /* ok */ File a DMD bug. (Also, you can use static assert here to check the assertions at build-time instead of run-time)
is(typeof()) gives the expected results: import std.traits : isNumeric; import std.range : isInputRange; void foo(T, U)(T x, U y) if (isNumeric!T && isNumeric!U) { } void bar(T, U)(T x, U y) if (isNumeric!T && isInputRange!U) { } unittest { static assert(is(typeof(foo!(int, int)))); //I get this static assert(!is(typeof(foo!(bool, bool)))); //I get this static assert(!is(typeof(foo!(int)))); //I think I get this static assert(is(typeof(bar!(int, int[])))); //I get this static assert(!is(typeof(bar!(int, int)))); //I get this static assert(!is(typeof(bar!(int)))); //I don't get this } (note well I have changed the assertion 3 and 6). There must be a subtle difference between __traits(compile,...) and is(typeof()). Does "compiles" mean that you've get something but that this thing is not always of a valid type ?
Apr 07 2016
parent jmh530 <john.michael.hall gmail.com> writes:
It looks like the bug has already been reported. There are a few 
associated with __traits(compiles), but this one seems most 
relevant:
https://issues.dlang.org/show_bug.cgi?id=3448

It also suggests that this is relevant:
https://issues.dlang.org/show_bug.cgi?id=965
Apr 08 2016