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 может доказать, что это не всегда невозможно обойти, но в целом стандарт запрещает его.