5 votes

L'ISO C++ déclare que ces deux éléments sont ambigus, même si la pire conversion pour le premier est meilleure que la pire conversion pour le second.

Pourquoi cette ambiguïté ?

// In class declaration
template<typename T>
class threadsafe_list {
    void for_each(std::function<void(T&)> _consumer);
    void for_each(std::function<void(const T&)> _consumer) const;
}

// Calling for_each
threadsafe_list<bool> list;

std::function<void(const bool&)> print = [](const bool& _bool) {
    std::cout << (_bool ? "True" : "False") << std::endl;
};

// Warning: for_each is ambiguous
list.for_each(print);

// This is OK
list.for_each([](const bool& _bool) { std::cout << (_bool ? "True" : "False") << std::endl; }); 

Pourquoi ce qui précède est-il ambigu ? L'un des for_each est destiné à const alors que l'autre ne l'est pas. Merci !

8voto

n.m. Points 30344

Il existe deux résolutions de surcharge possibles pour le premier appel, chacune impliquant une conversion :

  1. Choisissez la première surcharge, convertissez std::function<void(const bool&)> std::function<void(bool&)>
  2. Choisissez la deuxième surcharge, convertissez threadsafe_list<bool>& const threadsafe_list<bool>&

Aucune des deux conversions n'est meilleure que l'autre car elles s'appliquent à des arguments différents.

Pour le deuxième appel, l'un est meilleur que l'autre car le plus mauvais convertit les deux arguments (le lambda en std::function y list a const threadsafe_list<bool>& ).

Pour résoudre ce problème, vous pouvez ajouter une autre surcharge qui serait mieux adaptée que les deux premières :

void for_each(std::function<void(T&)> _consumer) const;

ou, alternativement, supprimez simplement std::function complètement pour assurer une correspondance exacte de l'argument :

template <typename F>
void for_each(F _consumer);
template <typename F>
void for_each(F _consumer) const;

2voto

Caleth Points 17517

La raison de l'ambiguïté dans le premier cas est que list n'est pas const donc l'argument implicite qui devient this a une conversion de qualification, et l'autre surcharge a un std::function<void(const bool&)> a std::function<void(bool&)> conversion.

L'autre cas n'est pas ambigu parce qu'il y a une conversion pour les deux arguments dans la fonction const mais seulement pour _consumer dans le cas du mutable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X