С++ max() с именем инициализатора возвращает строки не в порядке

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

в то время как

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

и

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

верните "z", как они должны. Почему?

Ответ 1

"a", "b" и т.д. являются строковыми литералами. Они распадаются на const char*, когда в списке инициализаторов. max просто, вероятно, получает тот, у которого самый высокий адрес, но поскольку он использует operator< для сравнения, и они не являются частью одного и того же массива или одного из тех же массивов, результат сравнения неуточнен (а вызов max приведет к поведению undefined, так как требование состоит в том, чтобы тип <LessThanComparable).

Два других вызова max определены корректно. char, такие как a, b и т.д. являются целыми типами с четко определенным меньшим сравнением. И std::string имеет operator<, который реализует лексикографическое сравнение.

Ответ 2

max({"a", "b", "z", "x"}); пытается сравнить указатели. Это имеет поведение undefined (поскольку результаты отдельных сравнений не указаны). Это вы хотели сравнить указатели, вы должны написать:

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

В отличие от этого, max({'a', 'b', 'z', 'x'}); сравнивает интегральные значения, а max<std::string> сравнивает строки.