web-dev-qa-db-fra.com

Pourquoi le nombre d'éléments dans une liste d'initialisation provoque-t-il une erreur d'appel ambigu?

Pourquoi les deux premiers appels à doSomething OK par le compilateur, mais l'utilisation de deux éléments dans la liste provoque un appel ambigu?

#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;
}
59
koolbanana

Ce qui se passe ici, c'est que dans la liste d'initialisation à deux éléments, les deux littéraux de chaîne peuvent être implicitement convertis en const char* puisque leur type est const char[N]. Maintenant std::vector a un constructeur qui prend deux itérateurs auxquels les pointeurs peuvent prétendre. Pour cette raison, le initializer_list constructeur du std::vector<std::string> est en conflit avec le constructeur de la gamme d'itérateurs de std::vector<int>.

Si nous changeons le code à la place

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

Ensuite, les éléments de la liste d'initialisation sont maintenant std::strings donc il n'y a pas d'ambiguïté.

58
NathanOliver

Les listes à un argument et à trois arguments ne peuvent correspondre qu'à std::vector<std::string>'s std::initializer_list constructeur. Cependant, la liste à deux arguments correspond à l'un des constructeurs de std::vector<int>:

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

En effet, un char const * peut être incrémenté et déréférencé pour obtenir un char qui est implicitement convertible en int.

23
Quentin

"hello" et "stack" se désintègrent tous deux en const char * ce qui satisfait le concept InputIterator . Cela leur permet de faire correspondre std::vector le constructeur # 4 .

Si vous passez des objets std::string, l'ambiguïté est résolue.

16
François Andrieux