Bug 7110 – opSlice() & opIndex functions works unstable as template arguments
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Windows
Creation time
2011-12-14T05:29:00Z
Last change time
2015-06-09T05:11:48Z
Keywords
pull, rejects-valid
Assigned to
nobody
Creator
verylonglogin.reg
Comments
Comment #0 by verylonglogin.reg — 2011-12-14T05:29:58Z
---
struct S { }
struct Call
{
static S opSlice() { return S(); }
static S opIndex(size_t) { return S(); }
}
template Template(Args...)
{
static assert(is(typeof(Args[0]) == S));
}
alias Template!(S()) A0; // passes
alias Template!(Call.opSlice()) A1; // passes
alias Template!(Call.opIndex(0)) A2; // passes
alias Template!(Call[]) A3; // failes
alias Template!(Call[0]) A4; // failes
---
Comment #1 by robert — 2011-12-14T05:54:49Z
I believe this is invalid - here Call[] is a dynamic array of Call, and Call[0] is a static array of Call, length zero. You can work around this using:
----
alias Template!({ return Call[]; }()) A3;
alias Template!({ return Call[0]; }()) A4;
----
Comment #2 by verylonglogin.reg — 2011-12-14T06:05:10Z
Thanks! I'm completely wrong here.
Comment #3 by verylonglogin.reg — 2011-12-14T07:06:17Z
And an easier workaround:
---
alias Template!((Call[])) A3; // passes
alias Template!((Call[0])) A4; // passes
---
But isn't it strange? Looks like this workaround is a bug. It leads to things like this:
---
struct S
{
int opSlice(int, int) const { return 0; }
int opSlice() const { return 0; }
int opIndex(int, int) const { return 0; }
int opIndex(int) const { return 0; }
}
enum e = S();
template T(alias a) { } // or T(a...)
alias T!( S ) T0; // passes
alias T!((S)) T1; // passes
alias T!( S()[0..0] ) A0; // passes
alias T!( (e[0..0]) ) A1; // passes
alias T!( e[0..0] ) A2; // passes
alias T!( S()[0, 0] ) B0; // passes
alias T!( (e[0, 0]) ) B1; // passes
alias T!( e[0, 0] ) B2; // passes
alias T!( S()[] ) C0; // passes
alias T!( (e[]) ) C1; // passes
alias T!( e[] ) C2; // fails: e is used as a type
alias T!( S()[0] ) D0; // passes
alias T!( (e[0]) ) D1; // passes
alias T!( e[0] ) D2; // fails: e must be an array or pointer type, not S
---
And the last error message looks wrong.