Issue 5371 - ambiguous stringnize of class with alias this

By fixing bug 2777, we can implement StringTypeOf more properly.
This commit is contained in:
k-hara 2011-09-10 23:32:48 +09:00
parent 740f3ec78a
commit e34a7debfd
2 changed files with 43 additions and 72 deletions

View file

@ -1261,10 +1261,11 @@ if (isSomeChar!T)
void formatValue(Writer, T, Char)(Writer w, T val, ref FormatSpec!Char f) void formatValue(Writer, T, Char)(Writer w, T val, ref FormatSpec!Char f)
if (isSomeString!T && !isStaticArray!T && !is(T == enum)) if (isSomeString!T && !isStaticArray!T && !is(T == enum))
{ {
Unqual!(StringTypeOf!T) str = val; // for `alias this`, see bug5371
if (f.spec == 's') if (f.spec == 's')
{ {
StringTypeOf!T val2 = val; // for `alias this` auto s = str[0 .. f.precision < $ ? f.precision : $];
auto s = val2[0 .. f.precision < $ ? f.precision : $];
if (!f.flDash) if (!f.flDash)
{ {
// right align // right align
@ -1282,17 +1283,17 @@ if (isSomeString!T && !isStaticArray!T && !is(T == enum))
} }
else else
{ {
static if (is(typeof(val[0]) : const(char))) static if (is(typeof(str[0]) : const(char)))
{ {
formatRange(w, val, f); formatRange(w, str, f);
} }
else static if (is(typeof(val[0]) : const(wchar))) else static if (is(typeof(str[0]) : const(wchar)))
{ {
formatRange(w, val, f); formatRange(w, str, f);
} }
else static if (is(typeof(val[0]) : const(dchar))) else static if (is(typeof(str[0]) : const(dchar)))
{ {
formatRange(w, val, f); formatRange(w, str, f);
} }
} }
} }
@ -1306,6 +1307,28 @@ unittest
assert(w.data == "abc"); assert(w.data == "abc");
} }
unittest
{
// 5371
class C1
{
const(string) var = "C1";
alias var this;
}
class C2
{
string var = "C2";
alias var this;
}
auto c1 = new C1();
auto c2 = new C2();
FormatSpec!char f;
auto a = appender!string();
formatValue(a, c1, f);
formatValue(a, c2, f);
}
/** /**
Input ranges are formatted like arrays. Input ranges are formatted like arrays.
*/ */

View file

@ -3196,75 +3196,23 @@ version (unittest) private template Intify(T) { alias int Intify; }
*/ */
template StringTypeOf(T) if (isSomeString!T) template StringTypeOf(T) if (isSomeString!T)
{ {
static if (is(T == class) || is(T == struct)) alias typeof(T.init[]) StringTypeOf;
{
static if (is(T : const(char[])))
{
static if (is(T : char[]))
alias char[] StringTypeOf;
else static if (is(T : immutable(char[])))
alias immutable(char)[] StringTypeOf;
else
alias const(char)[] StringTypeOf;
}
else static if (is(T : const(wchar[])))
{
static if (is(T : wchar[]))
alias wchar[] StringTypeOf;
else static if (is(T : immutable(wchar[])))
alias immutable(wchar)[] StringTypeOf;
else
alias const(wchar)[] StringTypeOf;
}
else
{
static if (is(T : dchar[]))
alias dchar[] StringTypeOf;
else static if (is(T : immutable(dchar[])))
alias immutable(dchar)[] StringTypeOf;
else
alias const(dchar)[] StringTypeOf;
}
}
else
{
alias T StringTypeOf;
}
} }
unittest unittest
{ {
class C(Char, int n) foreach (Ch; TypeTuple!(char, wchar, dchar))
{ {
static if (n==0) Char[] val; foreach (Char; TypeTuple!(Ch, const(Ch), immutable(Ch)))
static if (n==1) const(Char)[] val; {
static if (n==2) const(Char[]) val; foreach (Str; TypeTuple!(Char[], const(Char[]), immutable(Char[])))
static if (n==3) immutable(Char)[] val; {
static if (n==4) immutable(Char[]) val; class C(Str) { Str val; alias val this; }
alias val this; struct S(Str) { Str val; alias val this; }
}
struct S(Char, int n)
{
static if (n==0) Char[] val;
static if (n==1) const(Char)[] val;
static if (n==2) const(Char[]) val;
static if (n==3) immutable(Char)[] val;
static if (n==4) immutable(Char[]) val;
alias val this;
}
foreach (Char; TypeTuple!(char, wchar, dchar))
{
static assert(is(StringTypeOf!(C!(Char, 0)) == Char[]));
static assert(is(StringTypeOf!(C!(Char, 1)) == const(Char)[]));
static assert(is(StringTypeOf!(C!(Char, 2)) == const(Char)[])); // cannot get exact string type
static assert(is(StringTypeOf!(C!(Char, 3)) == immutable(Char)[]));
static assert(is(StringTypeOf!(C!(Char, 4)) == immutable(Char)[])); // cannot get exact string type
static assert(is(StringTypeOf!(C!Str) == Str));
static assert(is(StringTypeOf!(S!(Char, 0)) == Char[])); static assert(is(StringTypeOf!(S!Str) == Str));
static assert(is(StringTypeOf!(S!(Char, 1)) == const(Char)[])); }
static assert(is(StringTypeOf!(S!(Char, 2)) == const(Char)[])); // cannot get exact string type }
static assert(is(StringTypeOf!(S!(Char, 3)) == immutable(Char)[]));
static assert(is(StringTypeOf!(S!(Char, 4)) == immutable(Char)[])); // cannot get exact string type
} }
} }