The following program compiles without errors or warning with 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 with the same options gives this error:
error: non-type template argument evaluates to -1, which cannot be narrowed to type 'unsigned int' [-Wc++11-narrowing]
As per this question, it looks like gcc's present policy just to give warnings for narrowing conversions where the Standard indicates errors, and where clang gives the indicated errors. But in this case gcc does not even give a warning.
None of the examples of narrowing conversion errors that are given by the Standard at § 8.5.4/7 (reproduced in that question) covers the case of a narrowing conversion of a non-type template argument, but at § 14.3.2/5 the Standard says:
For a non-type template-parameter of integral or enumeration type, conversions permitted in a con- verted constant expression (5.19) are applied.
And § 5.19/3 says:
A converted constant expression of type T is a literal constant expression, implicitly converted to type T, where the implicit conversion (if any) is permitted in a literal constant expression and the implicit conversion sequence contains only user-defined conversions, lvalue-to-rvalue conversions (4.1), integral promotions (4.5), and integral conversions (4.7) other than narrowing conversions (8.5.4)
(my emphasis).
This seems to me to mean that even by its own yardstick gcc is at fault in not at all diagnosing a narrowing conversion in this case. Do I read this right? Is there a Standard-based counter-argument?
I am asking the question with more feeling that mere curiosity. In a recursive TMP setting, clang's error diagnostic in this case will pinpoint a bug in which an unsigned non-type template argument falls through 0, whereas all you get from gcc is "maximum template instantiation depth exceeded".