Правила условного оператора в черновике n3225 гласят в одной точке
В противном случае результат является prvalue.Если второй и третий операнды не имеют один и тот же тип и оба имеют (возможно, cv-квалифицированный) тип класса, разрешение перегрузки используется для определения преобразований (если они есть), которые должны применяться к операндам (13.3.1.2, 13.6),Если не удается разрешить перегрузку, программа работает некорректно.В противном случае, определенные таким образом преобразования применяются, и преобразованные операнды используются вместо исходных операндов в оставшейся части этого раздела.
До этой точки, любая другая альтернатива (например, преобразовать одинк другому операнду) не удалось, поэтому теперь мы будем делать то, что говорится в этом абзаце.Преобразования, которые мы будем применять, определяются разрешением перегрузки путем преобразования a ? b : c
в operator?(a, b, c)
(воображаемый вызов функции так называемой функции).Если вы посмотрите, каковы кандидаты в мнимые operator?
, вы найдете (среди прочих)
для каждого типа T, где T - указатель, указатель на член или тип перечисления с областью видимостиСуществуют операторные функции-кандидаты вида
T operator?(bool, T , T );
И это включает кандидата, для которого T
является типом void(*)()
.Это важно, потому что лямбда-выражения дают объект класса, который можно преобразовать в такой тип.В спецификации говорится:
Тип закрытия для лямбда-выражения без лямбда-захвата имеет открытую не виртуальную неявную функцию преобразования констант в указатель на функцию, имеющую тот же параметр и возвращаемый тип, что иоператор вызова функции типа закрытия.Значение, возвращаемое этой функцией преобразования, должно быть адресом функции, которая при вызове имеет тот же эффект, что и вызов оператора вызова функции типа замыкания.
Лямбда-выражения не могут быть преобразованы влюбой другой из перечисленных типов параметров, что означает, что разрешение перегрузки успешно выполняется, находит один operator?
и преобразует оба лямбда-выражения в указатели на функции.Затем оставшаяся часть секции условного оператора будет работать как обычно, теперь у нее есть две ветви для условного оператора того же типа.
Вот почему ваша первая версия в порядке, и поэтому GCC принимает ее правильно.Однако я не совсем понимаю, почему вы показываете вторую версию вообще - как объяснили другие, она делает что-то другое, и неудивительно, что она работает, а другая - нет (на вашем компиляторе).В следующий раз лучше постараться не включать бесполезный код в вопрос.