-1

I am learning about non-type template parameters using C++ Primer 5th edition and came to know that:

A nontype parameter may be an integral type, or a pointer or (lvalue) reference to an object or to a function type. An argument bound to a nontype integral parameter must be a constant expression.

Now to further clear my concept and confirm that I've understood the topic correctly, I wrote the following program that compiles with msvc but not with clang. Demo

#include <iostream>

template<char N> class S
{
public:
    S() 
    { 
        std::cout << "char template" << std::endl; 
    }
};

int main()
{
    S<128> s1; //MSVC compiles this but gcc and clang rejects   
}

So my question is which compiler is right here(if any). I tried to look this up in the book itself but I couldn't figure out whether the program is valid according to the c++ standard. MSVC compiles this while gcc and clang says:

error: non-type template argument evaluates to 128, which cannot be narrowed to type 'char'
Jason
  • 36,170
  • 5
  • 26
  • 60
Alex
  • 318
  • 1
  • 14
  • This is invalid because conversion from int `128` to `char` is a narrowing conversion(since msvc, gcc and clang all uses `char` as signed). You can try `char ch{128};` and you'll get the error with msvc also. So definitely a [msvc bug](https://developercommunity.visualstudio.com/t/MSVC-compiles-invalid-narrowing-conversi/10177081). – Jason Oct 19 '22 at 14:13
  • Dup of [Are narrowing conversions in non-type template parameters required to be diagnosed?](https://stackoverflow.com/questions/26309910/are-narrowing-conversions-in-non-type-template-parameters-required-to-be-diagnos) – Language Lawyer Oct 19 '22 at 14:46

1 Answers1

1

The program is ill-formed and msvc is wrong in accepting the code because the conversion from integer literal 128 to char is a narrowing conversion which is not permitted in this context as explained below. Basically this fails for the same reason that char ch{128}; fails which is that both of these involve integral conversion with narrowing conversion.

From temp.arg.nontype#2:

A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter.

Now from converted constant expression:

4) A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is a constant expression and the implicit conversion sequence contains only

4.7) integral conversions other than narrowing conversions

But note the integral conversion from int 128 to char is a narrowing conversion as can be seen from narrowing conversion:

7) A narrowing conversion is an implicit conversion

7.4) from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.

(emphasis mine)

Thus in case char is signed, the integral conversion from int 128 to char involves narrowing conversion and so is not allowed(not a converted constant expression) and hence msvc is wrong in accepting the code.

Here is the msvc bug report:

MSVC compiles invalid narrowing conversion in nontype template argument

Jason
  • 36,170
  • 5
  • 26
  • 60