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;