Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::initializer_list type deduction

Recently I wrote a very simple class.

class C
{
public:
    void AddString(std::initializer_list<std::pair<const char*,int>> x)
    {
          //irrelevant
    }
};

int main()
 {
           C c;
           c.AddString({ {"1",1}, {"2", 2}, {"3", 3} });
           .... //other unimportant stuff
           return 0;
 }

To my pleasant surprise it compiled and worked correctly. Can someone please explain to me how the compiler was able to deduce the nested braced initializers were for a std::pair? I am using MSVS 2013.

like image 810
pebbleonthebeach Avatar asked May 21 '15 00:05

pebbleonthebeach


1 Answers

c.AddString({ {"1",1}, {"2", 2}, {"3", 3} });

You're passing a braced-init-list, which itself contains nested brace-init-lists to AddString. The argument can match the std::initializer_list<std::pair<const char*,int>> parameter if the inner braced-init-lists can be converted to std::pair<const char*,int>.

This process of overload resolution occurs in two steps; first an attempt is made to match constructors of std::pair that take an std::initializer_list argument. Since std::pair has no such constructor, the second step occurs, where the other constructors of std::pair<const char*,int> are enumerated with char const[2] and int as the arguments. This will match the following pair constructor because char const[2] is implicitly convertible to char const * and the constructor itself is not explicit.

template< class U1, class U2 >
constexpr pair( U1&& x, U2&& y );

Quoting N3337 §13.3.1.7/1 [over.match.list]

When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:
— Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.
If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

If the initializer list has no elements and T has a default constructor, the first phase is omitted. In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.

like image 71
Praetorian Avatar answered Sep 28 '22 02:09

Praetorian