Unfortunately, the two function templates used in the last section are not allowed by the C++ Annotated Reference Manual (ARM) [ES90]. On pg. 347 of the ARM there is a categorical rule:
All template-args for a function template must be type-arguments.We violate this rule, since our template arguments are ints. We can avoid the problem for the operator+ function by simply redefining operator+ as a member function of the Dim class. However, in the absence of nested template declarations (the ARM forbids them), we cannot declare operator* to be a member function as there does not appear to be any way to bind the template arguments of the second operand. We are left with no choice but to use a function template to define operator*. This makes our programs violate the language definition and unacceptable to at least one existing compiler (Borland's BCC 4.0). Fortunately, another existing compiler (the Free Software Foundation's G++ [Sta93]) accepts such function templates.
The justification presented by the ARM for the problematic rule is that template arguments ``must be deduced from actual arguments in calls of the template function.'' The rule appears to be too strong for its justification; in fact the weaker rule on pg. 346 of the ARM
Every template-arg specified in the template-arg-list must be used in the argument types of a function template.appears to be sufficient, and eliminates our problem.
Another problem with forbidding function templates with non-type template arguments, is that it appears impossible to define a non-inline function which is a friend of a class which uses non-type template arguments. Also, since there are no restrictions on the use of non-type template arguments within member functions, permitting their use in function templates should not add greatly to the complexity of a compiler. Hence, even if it is not possible to allow such function templates in the language definition, compiler writers could permit their use as a language extension.