This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 113d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-03-20


1809. Narrowing and template argument deduction

Section: 13.10.3  [temp.deduct]     Status: CD4     Submitter: Richard Smith     Date: 2013-11-12

[Moved to DR at the November, 2014 meeting.]

13.10.3 [temp.deduct] paragraph 9 reads,

Except as described above, the use of an invalid value shall not cause type deduction to fail. [Example: In the following example 1000 is converted to signed char and results in an implementation-defined value as specified in (7.3.9 [conv.integral]). In other words, both templates are considered even though 1000, when converted to signed char, results in an implementation-defined value.

  template <int> int f(int);
  template <signed char> int f(int);
  int i1 = f<1>(0);      // ambiguous
  int i2 = f<1000>(0);   // ambiguous

end example]

This is no longer correct, even ignoring the fact that some implementations may be able to represent the value 1000 as a signed char: integral and enumeration non-type template arguments are now converted constant expressions (13.4.3 [temp.arg.nontype] paragraph 1), and converted constant expressions disallow narrowing conversions (7.7 [expr.const] paragraph 3).

Proposed resolution (February, 2014):

Change 13.10.3 [temp.deduct] paragraph 9 as follows:

Except as described above, the use of an invalid value shall not cause type deduction to fail. [Example: In the following example, 1000 is converted to signed char and results in an implementation-defined value as specified in (7.3.9 [conv.integral]). In other words, both templates are considered even though 1000, when converted to signed char, results in an implementation-defined value assuming a signed char cannot represent the value 1000, a narrowing conversion would be required to convert the template-argument of type int to signed char, therefore substitution fails for the second template (13.4.3 [temp.arg.nontype])..

  template <int> int f(int);
  template <signed char> int f(int);
  int i1 = f<1000>(0);       // ambiguous OK
  int i2 = f<1000>(0);       // ambiguous; not narrowing

end example]