www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template pred is true for pred!(pred!(pred)) but not for value "true"

reply "Meta" <jared771 gmail.com> writes:
template canBeAlias(T...)
if (T.length == 1)
{
	static if (is(typeof({alias _ = T[0];})))
	{
		enum canBeAlias = true;
	}
	else
	{
		enum canBeAlias = false;
	}
}

pragma(msg, canBeAlias!canBeAlias); //prints "true"
static assert(!canBeAlias!true); //passes
static assert(canBeAlias!(canBeAlias!canBeAlias)); //passes?!

What is going on here? `canBeAlias!canBeAlias` evaluates down to 
true, so why is `canBeAlias!true` false when 
`canBeAlias!(canBeAlias!canBeAlias)` is true?
Mar 08 2015
parent reply "anonymous example.com" <anonymous example.com> writes:
On Sunday, 8 March 2015 at 15:41:23 UTC, Meta wrote:
 template canBeAlias(T...)
 if (T.length == 1)
 {
 	static if (is(typeof({alias _ = T[0];})))
 	{
 		enum canBeAlias = true;
 	}
 	else
 	{
 		enum canBeAlias = false;
 	}
 }

 pragma(msg, canBeAlias!canBeAlias); //prints "true"
 static assert(!canBeAlias!true); //passes
 static assert(canBeAlias!(canBeAlias!canBeAlias)); //passes?!

 What is going on here? `canBeAlias!canBeAlias` evaluates down 
 to true, so why is `canBeAlias!true` false when 
 `canBeAlias!(canBeAlias!canBeAlias)` is true?
I get an error on your code: "test.d(16): Error: static assert (canBeAlias!(true)) is false". But when commenting out the first assert (line 15), there's no error. Played around with it, and I think it's a bug in the compiler: ---- /* The differently numbered 'canBeAliasN' are all the same. */ enum true_ = true; enum canBeAlias1(T...) = is(typeof({alias _ = T[0];})); pragma(msg, canBeAlias1!true); /* "false" */ enum canBeAlias2(T...) = is(typeof({alias _ = T[0];})); pragma(msg, canBeAlias2!true_); /* "true" */ enum canBeAlias3(T...) = is(typeof({alias _ = T[0];})); pragma(msg, canBeAlias3!true, " ", canBeAlias3!true_); /* "false false" */ enum canBeAlias4(T...) = is(typeof({alias _ = T[0];})); pragma(msg, canBeAlias4!true_, " ", canBeAlias4!true); /* "true true" */ ---- On their own, `canBeAlias!true` = false and `canBeAlias!true_` = true. This makes sense, because `true_` is a symbol whereas `true` is a value. But the two instantiations are apparently recognized as equivalent. Whichever is instantiated first, its value is used for the other instantiation, too. I think this behaviour is wrong.
Mar 08 2015
parent reply "Meta" <jared771 gmail.com> writes:
On Sunday, 8 March 2015 at 20:36:34 UTC, anonymous wrote:
 I get an error on your code: "test.d(16): Error: static assert  
 (canBeAlias!(true)) is false". But when commenting out the 
 first assert (line 15), there's no error.
Hmm, I might have made a mistake reducing my actual code.
 Played around with it, and I think it's a bug in the compiler:

 ----
 /* The differently numbered 'canBeAliasN' are all the same. */

 enum true_ = true;

 enum canBeAlias1(T...) = is(typeof({alias _ = T[0];}));
 pragma(msg, canBeAlias1!true); /* "false" */

 enum canBeAlias2(T...) = is(typeof({alias _ = T[0];}));
 pragma(msg, canBeAlias2!true_); /* "true" */

 enum canBeAlias3(T...) = is(typeof({alias _ = T[0];}));
 pragma(msg, canBeAlias3!true, " ", canBeAlias3!true_); /* 
 "false false" */

 enum canBeAlias4(T...) = is(typeof({alias _ = T[0];}));
 pragma(msg, canBeAlias4!true_, " ", canBeAlias4!true); /* "true 
 true" */
 ----

 On their own, `canBeAlias!true` = false and `canBeAlias!true_` 
 = true. This makes sense, because `true_` is a symbol whereas 
 `true` is a value.

 But the two instantiations are apparently recognized as 
 equivalent. Whichever is instantiated first, its value is used 
 for the other instantiation, too. I think this behaviour is 
 wrong.
Yeah, definitely wrong. template canBeAlias(T...) if (T.length == 1) { static if (is(typeof({alias _ = T[0];}))) { enum canBeAlias = true; } else { enum canBeAlias = false; } } void main() { pragma(msg, canBeAlias!canBeAlias); //prints "true" static assert(canBeAlias!(canBeAlias!canBeAlias)); //passes?! static assert(!canBeAlias!true); //Error: static assert(!true) is false } OR void main() { pragma(msg, canBeAlias!canBeAlias); //prints "true" static assert(!canBeAlias!true); //passes //Error: static assert (canBeAlias!(true)) is false static assert(canBeAlias!(canBeAlias!canBeAlias)); } So it definitely does depend on which comes first. This is a weird bug...
Mar 08 2015
parent reply "Meta" <jared771 gmail.com> writes:
On Sunday, 8 March 2015 at 21:11:12 UTC, Meta wrote:
 Yeah, definitely wrong.

 template canBeAlias(T...)
 if (T.length == 1)
 {
 	static if (is(typeof({alias _ = T[0];})))
 	{
 		enum canBeAlias = true;
 	}
 	else
 	{
 		enum canBeAlias = false;
 	}
 }

 void main()
 {
     pragma(msg, canBeAlias!canBeAlias); //prints "true"
     static assert(canBeAlias!(canBeAlias!canBeAlias)); 
 //passes?!
     static assert(!canBeAlias!true); //Error: static 
 assert(!true) is false
 }

 OR

 void main()
 {
     pragma(msg, canBeAlias!canBeAlias); //prints "true"
     static assert(!canBeAlias!true); //passes
     //Error: static assert (canBeAlias!(true)) is false
     static assert(canBeAlias!(canBeAlias!canBeAlias));
 }

 So it definitely does depend on which comes first. This is a 
 weird bug...
Urgh, I'm all messed up now. The results in the second case are correct, but the results in the first case are wrong, as !canBeAlias!true should be !false, not !true.
Mar 08 2015
parent "Meta" <jared771 gmail.com> writes:
On Sunday, 8 March 2015 at 21:17:31 UTC, Meta wrote:
 Urgh, I'm all messed up now. The results in the second case are 
 correct, but the results in the first case are wrong, as 
 !canBeAlias!true should be !false, not !true.
I also get the same results with __traits(compiles, { alias _ = T[0]; }).
Mar 08 2015