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


¿Por qué las dos primeras llamadas a doSomething están bien por el compilador, pero el uso de dos elementos en la lista causa 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;
}
Author: NathanOliver, 2017-01-06

3 answers

Lo que está sucediendo aquí es que en la lista del inicializador de dos elementos, ambos literales de cadena se pueden convertir implícitamente a 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 iterador de std::vector<int>.

Si cambiamos el código para ser

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

Entonces los elementos de la lista inicializador son ahora std::strings por lo que hay no hay ambigüedad.

 56
Author: NathanOliver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-06 14:22:54

Tanto las listas de un argumento como las de tres argumentos solo pueden coincidir con el constructor std::vector<std::string> del std::initializer_list. 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 ser incrementado, y desreferenciado para obtener un char que es implícitamente convertible a un int.

 23
Author: Quentin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-06 14:22:14

"hello" y "stack" ambos decaen a const char *que satisface el concepto InputIterator. Esto les permite coincidir std::vector's constructor #4 .

Si pasa objetos std::string la ambigüedad se resuelve.

 16
Author: François Andrieux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-06 14:23:40