How to pass an array size as a template with template type?
Hmm, the Standard says in 14.8.2.4 / 15
:
If, in the declaration of a function template with a non-type template-parameter, the non-type template-parameter is used in an expression in the function parameter-list and, if the corresponding template-argument is deduced, the template-argument type shall match the type of the template-parameter exactly, except that a template-argument deduced from an array bound may be of any integral type.
Providing this example:
template<int i> class A { /* ... */ };template<short s> void f(A<s>);void k1() { A<1> a; f(a); // error: deduction fails for conversion from int to short f<1>(a); // OK}
That suggests that the compilers that fail to compile your code (apparently GCC and Digital Mars) do it wrong. I tested the code with Comeau, and it compiles your code fine. I don't think there is a different to whether the type of the non-type template parameter depends on the type of the type-parameter or not. 14.8.2.4/2
says the template arguments should be deduced independent from each other, and then combined into the type of the function-parameter. Combined with /15, which allows the type of the dimension to be of different integral type, i think your code is all fine. As always, i take the c++-is-complicated-so-i-may-be-wrong card :)
Update: I've looked into the passage in GCC where it spits out that error message:
... type = TREE_TYPE (size); /* The array bound must be an integer type. */ if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type)) { if (name) error ("size of array %qD has non-integral type %qT", name, type); else error ("size of array has non-integral type %qT", type); size = integer_one_node; type = TREE_TYPE (size); } ...
It seems to have missed to mark the type of the size as dependent in an earlier code block. As that type is a template parameter, it is a dependent type (see 14.6.2.1
).
Update: GCC developers fixed it: Bug #38950