Bug 9828 – Inconsistent lowering of 1-element tuple to its element

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-03-29T08:54:00Z
Last change time
2016-08-27T23:12:41Z
Assigned to
nobody
Creator
andrej.mitrovich

Comments

Comment #0 by andrej.mitrovich — 2013-03-29T08:54:26Z
template tuple(T...) { alias tuple = T; } template get(alias sym) { alias get = sym; } void main() { alias tuple!(int, float) IntFloat; // alias a = get!IntFloat; // does not match, OK alias tuple!(int) Int; // alias b = get!Int; // does not match, OK alias tuple!("foo", "bar") FooBar; // alias c = get!FooBar; // does not match, OK alias tuple!("foo") Foo; alias d = get!Foo; // works, ?? if (d == "foo") { } // works if (Foo == "foo") { } // does not work } It's really strange that a 1-element tuple seems to be implicitly convertible to its element type when it's passed by alias, yet we cannot directly compare a 1-element tuple against another element of the same type. Either it should be consistently allowed to use a 1-element tuple as if it were the element itself, or it should never be implicitly convertible to the element type. It should be consistent.
Comment #1 by andrej.mitrovich — 2013-03-29T08:59:30Z
Here's an example of why it would be useful if it's consistently allowed: import std.typetuple; template getTypes(T...) { alias getTypes = T; } void test(T)(T t) { alias attributes = getTypes!(__traits(getAttributes, T)); // NG: Even if tuple length is 1 // static if (attributes == "S1") { } // NG: '(string)' and '(string)' (why are they not comparable?) // static if (attributes == TypeTuple!("S1")) { } // Note: .length check is necessary, otherwise out of bounds errors occur static if (attributes.length && attributes[0] == "S1") { pragma(msg, T); } } void main() { @("S1") static struct S1 { } static struct S2 { } test(S1()); test(S2()); }
Comment #2 by k.hara.pg — 2013-07-23T18:39:52Z
(In reply to comment #0) > alias tuple!("foo") Foo; > alias d = get!Foo; // works, ?? Here's no inconsistency. If you give a tuple as template argument, it would be automatically expanded to its elements. And if the tuple contains just one symbol element, the template argument would match to alias version. > if (d == "foo") { } // works > if (Foo == "foo") { } // does not work OTOH, currently one-element tuple is not automatically expanded to the element itself on the each side of binary operator. I'm not sure this is well designed, but I think that holding the distinction of them would be valuable than mixing them.
Comment #3 by andrej.mitrovich — 2016-08-27T23:12:41Z
Indeed I came to the same conclusions. The tuple is only lowered on request, like for alias parameters. In the last code example `Foo[0]` should be used;