Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++'s max() with initializer list returns strings out of order

max({"a", "b", "z", "x"});  returns "x"

while both

max<std::string>({"a", "b", "z", "x"});

and

max({'a', 'b', 'z', 'x'});

return "z" as they should. Why?

like image 232
Mikhail Avatar asked Jul 01 '15 14:07

Mikhail


2 Answers

"a", "b" etc. are string literals. These decay to const char* when in the initializer list. max just probably gets the one with the highest address, but since it uses operator< to compare them, and they aren't part of the same array, or one-past the same array, the result of the comparison is unspecified (and the invocation of max would result in undefined behaviour, since the requirement is that the type be LessThanComparable).

The other two invocations of max are well defined. chars such as a, b etc. are integral types with a well defined less-than comparison. And std::string has an operator< that implements a lexicographical comparison.

like image 181
juanchopanza Avatar answered Nov 09 '22 16:11

juanchopanza


max({"a", "b", "z", "x"}); attempts to compare pointers. This has undefined behaviour (since the results of the individual comparisons are unspecified). It you wanted to compare pointers, you should write:

std::max({"a", "b", "z", "x"}, std::less<const char*>());

By contrast, max({'a', 'b', 'z', 'x'}); compares integral values, and max<std::string> compares strings.

like image 33
Kerrek SB Avatar answered Nov 09 '22 14:11

Kerrek SB