Ответ 1
Из стандарта (§14.3.2/5):
Следующие преобразования выполняются для каждого выражения, используемого в качестве шаблона-аргумента типа non-type. Если non-type template-argument не может быть преобразован в тип соответствующего шаблона-параметра, тогда программа плохо сформирована.
- Для нестандартного шаблона-параметра интегрального или перечисляемого типа применяются преобразования, разрешенные в преобразованном постоянном выражении (5.19).
В §5.19 мы узнаем (подчеркнув мое):
Интегральное постоянное выражение представляет собой выражение интегрального или неперечисленного типа перечисления, неявно преобразованного на prvalue, где преобразованное выражение является основным постоянным выражением.... Преобразованное постоянное выражение type
T
- это выражение, неявно преобразованное в prvalue типа T, где преобразованное выражение является ядром постоянное выражение и неявная последовательность преобразования содержит только пользовательские преобразования, lvalue-to-rvalue конверсий (4.1), интегральных повышений (4.5) и интегральных преобразований (4.7) , кроме сужения конверсий (8.5.4). [Примечание: такие выражения могут использоваться в новых выражениях (5.3.4), как выражения case (6.4.2), как инициализаторы перечисления, если базовый тип является фиксированным (7.2), как границы массива (8.3.4) и как интегральные или перечисление аргументов шаблона non-type (14.3). -end note]
Таким образом, сужение конверсий (например, преобразование 4
в bool
) явно запрещено для интегральных константных выражений, которые в этом случае необходимы как аргумент шаблона непигового типа. Это делает вызов f<4>()
неправильным.
Я считаю, что Clang корректен при выдаче ошибки, а GCC и VC являются несоответствующими для того, чтобы не выдавать никаких диагностических данных.
[Обновить] Это Ошибка GCС# 57891, похоже, что он в настоящее время не назначен.