During my research for an answer for this question I found (I did not know that before) that gcc and clang allow char
arrays to be template arguments if they are de
This is a change from C++14 to C++17 that looks like MSVS hasn't caught up with. Previously in [temp.arg.nontype] a non type argument had to be
A template-argument for a non-type, non-template template-parameter shall be one of:
for a non-type template-parameter of integral or enumeration type, a converted constant expression ([expr.const]) of the type of the template-parameter; or
the name of a non-type template-parameter; or
a constant expression ([expr.const]) that designates the address of a complete object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, where the id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
a constant expression that evaluates to a null pointer value ([conv.ptr]); or
a constant expression that evaluates to a null member pointer value ([conv.mem]); or
a pointer to member expressed as described in [expr.unary.op]; or
a constant expression of type
std::nullptr_t
.
emphasis mine
and because of bullet 3 you could not use a block scope variable as block scope variables have no linkage per [basic.link]/10
Names not covered by these rules have no linkage. Moreover, except as noted, a name declared at block scope has no linkage.
In C++17 this changes. [temp.arg.nontype] now has
A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
a subobject,
a temporary object,
a string literal,
the result of a typeid expression, or
a predefined func__ variable.
This now allows you to use a block scope static variable