Reputation: 81
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.
Upvotes: 8
Views: 828
Reputation: 109119
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 classT
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 classT
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 anexplicit
constructor is chosen, the initialization is ill-formed.
Upvotes: 9