Следующая программа компилируется без ошибок и предупреждений с помощью gcc 4.8.1, -Wall -std=c++11
:
template<unsigned N>
struct A{};
int main(){
A<1-2> a;
(void)a;
return 0;
}
clang 3.3 с теми же параметрами выдает такую ошибку:
ошибка: аргумент шаблона нетипа оценивается как -1, который не может быть сужен до типа 'unsigned int' [-Wc++11-narrowing]
Согласно этому вопросу, похоже, что текущая политика gcc просто выдает предупреждения о сужении конверсий, где стандарт указывает на ошибки, а где clang выдает указанные ошибки. Но в этом случае gcc даже не выдает предупреждения.
Ни один из примеров сужения ошибок преобразования, приведенных в Стандарте в § 8.5.4/7 (воспроизведен в этом вопросе ) охватывает случай сужающего преобразования аргумента шаблона, отличного от типа, но в § 14.3.2/5 Стандарт говорит:
Для нетипового шаблона-параметра интегрального или перечислительного типа применяются преобразования, разрешенные в преобразованном константном выражении (5.19).
И § 5.19/3 говорит:
Преобразованное константное выражение типа T является литеральным константным выражением, неявно преобразованным в тип T, где неявное преобразование (если таковое имеется) разрешено в литеральном константном выражении, а последовательность неявного преобразования содержит только определяемые пользователем преобразования, lvalue-to- преобразования rvalue (4.1), интегральные преобразования (4.5) и интегральные преобразования (4.7) кроме сужающих преобразований (8.5.4)
(выделено мной).
Мне кажется, это означает, что даже по собственным меркам gcc виноват в том, что в данном случае вообще не диагностирует сужающее преобразование. Я правильно это прочитал? Есть ли контраргумент, основанный на стандарте?
Я задаю вопрос больше с чувством, чем просто из любопытства. В рекурсивной настройке TMP диагностика ошибок clang в этом случае выявит ошибку, при которой неподписанный аргумент шаблона, не являющийся типом, падает ниже 0, тогда как все, что вы получаете от gcc, это «превышение максимальной глубины создания экземпляра шаблона».