if constexpr в рекурсивной общей лямбде: поведение другого компилятора

Следующий код успешно компилируется с g++ 7.3.0 и не может скомпилироваться с кланом g++ 6.0.0 (флагов компиляции являются -std=c++17 -Wall -Wextra -Werror -pedantic-errors):

auto foo = [](auto, auto... tail) {
    if constexpr (sizeof...(tail) > 0)
    {
        return foo(tail...);
    }
    else
    {
        return 42;
    }
};

int main()
{
}

clan g++ сообщение об ошибке компиляции:

error: переменная 'foo', объявленная с выведенным типом 'auto', не может появиться в своем собственном инициализаторе

return foo(tail...);

Какое поведение является стандартным в этом случае?

Ответы

Ответ 1

Клэнг прав отклонить это согласно [dcl.spec.auto]/10, как на С++ 17.

Если тип объекта с неопределенным типом заполнителя необходим для определения типа выражения, программа плохо сформирована.

Тип foo необходим для разрешения рекурсивного вызова (find operator() и т.д.). Ему необходимо было определить тип замыкания. Так как тип замыкания выводится здесь... вы видите, куда он идет.

GCC может доказать, что это не всегда невозможно обойти, но в целом стандарт запрещает его.