Ответ 1
См. пост Ричарда Смита на std-обсуждении:
В реализации я знаком с [т. Clang], ключевая проблема заключается в том, что лексические области, используемые при обработке определения функции, в корне преходящи, что означает, что отсрочить создание некоторой части определения шаблона функции трудно. Родовые лямбды не страдают от проблемы здесь, потому что тело общей лямбды создается с помощью шаблона закрывающей функции, [..]
То есть, общие тела lambdas частично создаются с использованием локального контекста (включая аргументы шаблона) при создании экземпляра шаблона; таким образом, при реализации Clang, T::x
и T::y
подставляются непосредственно, так как тип закрытия может быть передан за пределы. Это приводит к сбою. Как указано в [T.C.], Код можно считать плохо сформированным, не требуется диагностика, поскольку в экземпляре s<foo>
дается определение шаблона (закрытие), вторая ветвь if constexpr
не имеет корректных экземпляров. Это объясняет поведение как Clang, так и GCC.
Это сводится к архитектурной проблеме в крупной реализации (см. также этот ответ; GCC, по-видимому, не страдает от этого ограничения), поэтому я был бы удивил, если Core сочтет ваш код хорошо сформированным (в конце концов, они учли это при разработке общих лямбда-захватов - см. связанный ответ). GCC, поддерживающий ваш код, в лучшем случае является функцией (но, вероятно, вредной, так как позволяет писать код, зависящий от реализации).