Clang and GCC disagree on accepting this code.
What is the standard required behavior?
#include <utility>
#include <iostream>
#include <vector>
int main()
{
std::vector pairs = {std::pair{1,11},{2,22}, {3,33}};
for (const auto& p: pairs) {
std::cout << p.second << std::endl;
}
}
Note: I know this is C++ so it is possible that the standard is fuzzy, but I presume one behavior is correct.
The process of CTAD is largely defined by [over.match.class.deduct]. Broadly speaking, the overload set is all of the accessible constructors of the type, plus any deduction guides. And the overload set is resolved per this rule:
Since the "type of initialization performed" is definitely list-initialization, we move on to [over.match.list]. Where we get this infamous bulleted list:
This tells us that
initializer-list constructors
are prioritized; they're given first crack at overload resolution, and in a very specific way (that is, building astd::initializer_list
and passing it as an argument). However, Clang gives a telling error:That is, it's trying to call that constructor as if "the argument list consists of the elements of the initializer list." This suggests that Clang skipped the first bullet point when doing list-initialization through CTAD. The fact that adding parens around the braced-init-list "fixes" the issue also suggests that this is what is happening.
Oddly, it works for simple types, like an initializer-list of integers. And it works if you explicitly name each member as a
pair
. And Clang canauto
-deduce the type of theinitializer_list
produced by{std::pair{1,11}, {2,22}, {3,33}}
just fine. So this bug seems really specific.