Вопрос сводится к следующему: действительно ли decltype(&f<true, int>)
создает экземпляр f<true, int>
?
Если да, то программа плохо сформирована, потому что этот экземпляр плохо сформирован (не может вызвать g
с int
, как требуется).
Если нет, тогда правильный ответ для invocable_v
будет true
- поскольку в теле функции нет SFINAE, и сигнатура функции явно допускает этот вызов.
Похоже, что g cc считает, что да (и серьезные ошибки), а clang - нет (и выдает true
). Я думаю, что лязг здесь правильный. У нас есть следующие правила:
[temp.inst] / 10 :
Если в какой-либо форме используется шаблон функции или шаблон функции-члена при разрешении перегрузки неявно создается экземпляр специализации ([temp.over]).
[temp.inst] / 11 :
Реализация не должна неявно создавать экземпляр шаблона функции, шаблона переменной, шаблона элемента, не виртуальной функции-члена, класса-члена, элемента данных stati c шаблона класса или подстановки constexpr. оператор if ([stmt.if]), если только такое создание не требуется.
Мы включаем разрешение перегрузки здесь (адрес функции), но это только создание экземпляра объявления шаблона функции. Я не думаю, что что-то требует создания экземпляра определения шаблона функции (f
возвращает void
, а не что-то вроде auto
), поэтому g cc создает его здесь слишком охотно.
Тем не менее, конечно, это не должно давать false
.