Thread overview | ||||||
---|---|---|---|---|---|---|
|
April 07, 2016 __traits(compiles) and template instantiation | ||||
---|---|---|---|---|
| ||||
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 } |
April 07, 2016 Re: __traits(compiles) and template instantiation | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | 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)
|
April 08, 2016 Re: __traits(compiles) and template instantiation | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex Parrill | 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 ? |
April 08, 2016 Re: __traits(compiles) and template instantiation | ||||
---|---|---|---|---|
| ||||
Posted in reply to jkpl | 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 |
Copyright © 1999-2021 by the D Language Foundation