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

2024-11-11


2735. List-initialization and conversions in overload resolution

Section: 12.2.4  [over.match.best]     Status: open     Submitter: Jason Merrill     Date: 2023-03-23

There is implementation divergence in handling the following example:

  template <typename _Tp> struct optional {
    template <typename _Up> explicit optional(_Up);
    template <typename _Up = _Tp> void operator=(_Up);
  };
  struct SourceBrush {
    struct Brush {
     int brush;
    };
    void setPattern() { m_brush = {42}; }
    optional<Brush> m_brush;
  };

The following example is ambiguous per issue 1228:

  #include <unordered_set>
  #include <string>

  template<typename T> struct wrap {
    template<typename ...Ts> explicit wrap(Ts &&...args) : v(std::forward<Ts>(args)...) {}
    explicit wrap(const T &v) : v(v) {}
    explicit wrap(T &&v) : v(v) {}
    wrap(const wrap&) = delete;
    T v;
  };

  void f() {
    wrap<std::unordered_set<std::string>> wrapped_set({"foo", "bar", "baz"});
  }

The copy constructor of wrap<...> becomes viable, by way of constructing another wrap object from the given initializer list using the explicit constructor template. It looks like a deleted copy constructor is used to remove a level of braces, and then picking an explicit constructor to construct the source of the copy.

Another example:

  #include <string>
  #include <map>

  struct X {
    explicit X(const std::map<std::string, std::string> &map);
  };

  struct Y {
    Y() : x({{"foo", "bar"}}) {}
    X x;
  };

The intent is to construct the map with a single key-value pair, but the list-initialization is ambiguous with invoking the copy constructor and creating a map from a pair of iterators given by {"foo", "bar"}.

And another example:

  struct Z {};

  struct X {          
    explicit X(const Z &z = {});
  };

  struct Y {   
    Y() : x({}) {}                                            
    X x;
  };

The ambiguity is between

Core issue 2267 is also related.

Suggested resolution:

Insert before 12.2.4.1 [over.match.best.general] bullet 2.4 as follows: