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

2023-01-15


1543. Implicit conversion sequence for empty initializer list

Section: 12.2.4.2.6  [over.ics.list]     Status: CD3     Submitter: Steve Adamczyk     Date: 2012-08-21

[Moved to DR at the April, 2013 meeting.]

According to 12.2.4.2.6 [over.ics.list] paragraph 6, when passing an initializer-list argument to a non-class parameter,

if the initializer list has no elements, the implicit conversion sequence is the identity conversion.

However, there is no similar provision for an empty initializer list passed to a specialization of std::initializer_list or an array, as described in paragraph 2:

If the parameter type is std::initializer_list<X> or “array of X134 and all the elements of the initializer list can be implicitly converted to X, the implicit conversion sequence is the worst conversion necessary to convert an element of the list to X.

It is not clear what the result should be for a list with no elements. For example, given

  void f(int) { printf("int\n"); }
  void f(std::initializer_list<int>) { printf("init list\n"); }
  int main() {
      f({});
  }

current implementations result in init list being printed, presumably on the basis of the last bullet of 12.2.4.3 [over.ics.rank] paragraph 3:

That would imply that both conversion sequences are the identity conversion, which is reasonable, but it should be stated clearly if that is the intent.

Proposed resolution (October, 2012):

Change 12.2.4.2.6 [over.ics.list] paragraph 2 as follows:

If the parameter type is std::initializer_list<X> or “array of X134 and all the elements of the initializer list can be implicitly converted to X, the implicit conversion sequence is the worst conversion necessary to convert an element of the list to X, or if the initializer list has no elements, the identity conversion. This conversion can be a user-defined conversion even in the context of a call to an initializer-list constructor. [Example:

  void f(std::initializer_list<int>);
  f( {} );        // OK: f(initializer_list<int>) identity conversion
  f( {1,2,3} );   // OK: f(initializer_list<int>) identity conversion
  f( {'a','b'} ); // OK: f(initializer_list<int>) integral promotion
  f( {1.0} );     // error: narrowing
  ...