简体   繁体   中英

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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM