Неверно ли, что gcc не диагностирует сужающие преобразования в аргументах шаблона, отличного от типа?

Следующая программа компилируется без ошибок и предупреждений с помощью 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, это «превышение максимальной глубины создания экземпляра шаблона».


person Mike Kinghan    schedule 09.07.2013    source источник
comment
Стандарт никогда не требует ошибок или предупреждений — стандарт требует от реализации только выдачи диагностики. Принимает ли такая диагностика форму ошибки компилятора, предупреждения или чего-то совершенно отличного от них обоих, выходит за рамки стандарта.   -  person Casey    schedule 10.07.2013
comment
@Кейси. Я понимаю, но я сомневаюсь в отсутствии какой-либо диагностики; отсутствие чего-либо, кроме успеха.   -  person Mike Kinghan    schedule 10.07.2013
comment
@Кейси. Нет, мои извинения. Я сказал необходимые ошибки, и не должен был.   -  person Mike Kinghan    schedule 10.07.2013
comment
Я также понимаю, поэтому комментарий вместо ответа;)   -  person Casey    schedule 10.07.2013
comment
В С++ 03 это было допустимо (IIRC). -1 -> unsigned — это сужающее преобразование, поэтому GCC неправильно разрешает это в режиме C++ 11.   -  person Johannes Schaub - litb    schedule 10.07.2013


Ответы (1)


GCC не такой педантичный, как Clang, однако он все же может обнаруживать такие ошибки:

gcc -Wsign-conversion 1.cpp
1.cpp: In function 'int main()':
1.cpp:5:10: warning: negative integer implicitly converted to unsigned type [-Wsign-conversion]
     A<1-2> a;
          ^

-Wall на самом деле не включает все возможные проверки. Дополнительные примеры см. на этой странице: http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

Я использую gcc.EXE (GCC) 4.8.0 20130203 (experimental)

person Sergey K.    schedule 21.07.2013
comment
Это полезный момент (+1), но я не думаю, что это ответ. § 5.19/3 (в кавычках) разрешает преобразованное константное выражение неявно преобразовываться в целевой тип, но по-прежнему прямо запрещает сужающее преобразование. -Wsign-conversion дает полезную диагностику преобразования, разрешенного Стандартом. Таким образом, не активируется даже -pedantic, но даже при -pedantic нет диагностики сужающего преобразования, которое запрещено Стандартом. Это предупреждение GCC также распространено в C и намного старше, чем запрет сужающих преобразований в C++11. - person Mike Kinghan; 21.07.2013
comment
Я тоже пробовал -pedantic и был разочарован. Мне это кажется ошибкой компилятора. - person Sergey K.; 21.07.2013