On Monday, November 21, 2016 17:01:56 Stefan via Digitalmars-d-learn wrote: > Before 2.0.72.0: > > import std.algorithm : map, joiner; > import std.uni : toUpper; > import std.traits : EnumMembers; > import std.stdio : writeln; > import std.conv: to; > > private enum Color : string { > RED = "red", > BLUE = "blue", > YELLOW = "yellow" > } > > > void main(string[] args) { > writeln( [ EnumMembers!Color ].map!( toUpper ).joiner( ", " > ).to!string ); > } > > printed: > RED, BLUE, YELLOW > > Now I got the following compiler error: > C:\develop\dmd-2.072.0\windows\bin\..\..\src\phobos\std\uni.d(8142,16): > Error: cannot implicitly convert expression (result.data()) of type > string to Color > C:\develop\dmd-2.072.0\windows\bin\..\..\src\phobos\std\uni.d(9030,51): > Error: template instance std.uni.toCase!(toUpperIndex, 1051, toUpperTab, > toUpper, Color) error instantiating > C:\develop\dmd-2.072.0\windows\bin\..\..\src\phobos\std\algorithm\iterati > on.d(593,19): instantiated from here: toUpper!(Color) > C:\develop\dmd-2.072.0\windows\bin\..\..\src\phobos\std\algorithm\iterati > on.d(488,16): instantiated from here: MapResult!(toUpper, Color[]) > source\enums\enums.d(24,35): instantiated from here: > map!(Color[]) > source\enums\enums.d(24,58): Error: template > std.algorithm.iteration.joiner cannot deduce function from > argument types !()(MapResult!(toUpper, Color[]), string), > candidates are: > C:\develop\dmd-2.072.0\windows\bin\..\..\src\phobos\std\algorithm\iteratio > n.d(2050,6): std.algorithm.iteration.joiner(RoR, Separator)(RoR r, > Separator sep) if (isInputRange!RoR && isInputRange!(ElementType!RoR) && > isForwardRange!Separator && is(ElementType!Separator : > ElementType!(ElementType!RoR))) > C:\develop\dmd-2.072.0\windows\bin\..\..\src\phobos\std\algorithm\iterati > on.d(2333,6): std.algorithm.iteration.joiner(RoR)(RoR r) if > (isInputRange!RoR && isInputRange!(ElementType!RoR)) dmd failed with exit > code 1. > > Any idea how to fix it?
Casting [EnumMembers!Color] to string[] will probably do it as would using toUpper!string instead of toUpper. I think that the problem has to do with Color not being an actual range, but it passes isSomeString, resulting in a an ugly situation where the code basically assumes that it's dealing with a string when it isn't really, and the code doesn't actually work with an enum. Prior to 2.072.0, there was an overload for toUpper that took string as an optimization but that inadvertently meant that types that implicitly converted to strings worked with it and were converted to string, whereas with 2.072.0, they now have to pass isSomeString. In the case of a struct that implicitly converts to string or a static array of characters, it would now simply fails the template constraint and fail to compile, whereas for an enum with a base type of string, it's in this weird in between land where it passes isSomeString but really needs to actually be converted to string to work as a range. So, instead of failing the template constraint, it hits an error inside of the std.uni stuff. I think that the change is getting reverted for 2.072.1, because it broke existing code, but for now at least, enums aren't going to work with toUpper or toLower. Unfortunately, templated code that deals with strings needs to be _really_ careful about how it deals with enums with a base type of string, because they pass isSomeString but aren't actually strings (which is great for code that doesn't use the range API but falls flat on its face for code that does use the range API). Static arrays and structs which implicitly convert to strings have the same problem, but at least they don't pass isSomeString. In general, any type which implicitly converts to another type really needs to have that coversion forced with generic code that wants the converted type; otherwise, it's going to have a tendency to fall flat on its face. - Jonathan M Davis