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)
if (isSomeString!T && !isStaticArray!T && !is(T == enum))
{
Unqual!(StringTypeOf!T) str = val; // for `alias this`, see bug5371
if (f.spec == 's')
{
StringTypeOf!T val2 = val; // for `alias this`
auto s = val2[0 .. f.precision < $ ? f.precision : $];
auto s = str[0 .. f.precision < $ ? f.precision : $];
if (!f.flDash)
{
// right align
@ -1282,17 +1283,17 @@ if (isSomeString!T && !isStaticArray!T && !is(T == enum))
}
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");
}
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.
*/

View file

@ -3196,75 +3196,23 @@ version (unittest) private template Intify(T) { alias int Intify; }
*/
template StringTypeOf(T) if (isSomeString!T)
{
static if (is(T == class) || is(T == struct))
{
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;
}
alias typeof(T.init[]) StringTypeOf;
}
unittest
{
class C(Char, int n)
foreach (Ch; TypeTuple!(char, wchar, dchar))
{
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;
}
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
foreach (Char; TypeTuple!(Ch, const(Ch), immutable(Ch)))
{
foreach (Str; TypeTuple!(Char[], const(Char[]), immutable(Char[])))
{
class C(Str) { Str val; alias val this; }
struct S(Str) { Str val; alias val this; }
static assert(is(StringTypeOf!(S!(Char, 0)) == Char[]));
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
static assert(is(StringTypeOf!(C!Str) == Str));
static assert(is(StringTypeOf!(S!Str) == Str));
}
}
}
}