c++ initializer-list ambiguous overload-resolution

c++ - ¿Por qué el número de elementos en una lista de inicializador causa un error de llamada ambiguo?



initializer-list ambiguous (3)

Las listas de uno y tres argumentos solo pueden coincidir con el constructor std::vector<std::string> std::initializer_list std::vector<std::string> . Sin embargo, la lista de dos argumentos coincide con uno de los constructores de std::vector<int> :

template <class InputIt> vector(InputIt first, InputIt last, Allocator const &alloc = Allocator());

De hecho, un char const * puede incrementarse y desreferenciarse para obtener un char que sea convertible implícitamente en un int .

¿Por qué son las dos primeras llamadas a hacer algo correcto por el compilador, pero el uso de dos elementos en la lista provoca una llamada ambigua?

#include <vector> #include <string> void doSomething(const std::vector<std::string>& data) {} void doSomething(const std::vector<int>& data) {} int main(int argc, char *argv[]) { doSomething({"hello"}); // OK doSomething({"hello", "stack", "overflow"}); // OK doSomething({"hello", "stack"}); // C2668 ''doSomething'': ambiguous call return 0; }


Lo que sucede aquí es que en la lista de inicializadores de dos elementos, ambos literales de cadena se pueden convertir implícitamente en const char* ya que su tipo es const char[N] . Ahora std::vector tiene un constructor que toma dos iteradores para los que califican los punteros. Debido a eso, el constructor initializer_list de std::vector<std::string> está en conflicto con el constructor de rango de iterador de std::vector<int> .

Si cambiamos el código para que sea

doSomething({"hello"s, "stack"s});

Entonces, los elementos de la lista de inicializadores ahora son std::string s, por lo que no hay ambigüedad.