为什么std :: initializer_list转换不是首选?

vso*_*tco 11 c++ initializer-list overload-resolution c++11

请考虑以下代码段:

#include <iostream>
#include <vector>

void f(std::vector<int>){std::cout << __PRETTY_FUNCTION__ << '\n';}
void f(int x){std::cout << __PRETTY_FUNCTION__ << '\n';}

int main() 
{
    f({42});
}
Run Code Online (Sandbox Code Playgroud)

Live on Coliru

如果你运行它,你可以看到f(int)重载是首选,即使std::vector有一个std::initializer_list构造函数(见#8).

问题:为什么转换{42}int首选(而不是转换为std::vector,{42}std::initializer_list)?

son*_*yao 16

在重载决策中,当考虑列表初始化中的隐式转换序列时,

(强调我的)

否则,如果参数类型不是类并且初始化列表具有一个元素,则隐式转换序列是将元素转换为参数类型所需的序列

给定的f({42});f(int),隐式转换序列是将元素(即42)转换int为完全匹配的转换序列; 因为f(std::vector<int>),用户定义的转换(转换std::initializer_list<int>std::vector<int>)是必需的,那么这是一个更糟糕的匹配.

PS:如果braced-initializer包含多个元素{42, 42},f(std::vector<int>)则会被选中.