web-dev-qa-db-fra.com

Comparer std :: functions pour l'égalité?

Comment comparer deux std::functions C++ 11 avec operator== et renvoyer true si les deux functions font référence au même pointeur de fonction?

28
JesseTG

(opérateur == } pour std :: function compare un std :: function à un pointeur nul, pour autant que je sache, la norme ne fournit pas de détails sur la raison.

Bien que, cette entrée boost FAQ, Pourquoi ne puis-je pas comparer les objets boost :: function avec l'opérateur == ou l'opérateur! =? Fournit une justification et devrait, dans la mesure du possible, être applicable à std :: function également. Citant la FAQ:

La comparaison entre les objets boost :: function ne peut pas être "bien" implémentée et ne sera donc pas implémentée. [...]

il décrit ensuite les solutions demandées similaires à celles de Preet et poursuit:

Le problème se produit lorsque le type des objets fonction stockés à la fois par f et g n'a pas d'opérateur == [...]

et explique pourquoi cela doit être traité soit par l'opérateur d'affectation, soit par le constructeur, puis poursuit:

Tous ces problèmes se traduisent par des échecs dans les constructeurs boost :: function ou l'opérateur d'affectation, même si l'utilisateur n'invoque jamais l'opérateur ==. Nous ne pouvons pas faire cela aux utilisateurs.

Mettre à jour

Trouvé une logique de standard dans Accès à la cible d'un objet de fonction tr1 :: }, qui est assez ancien mais qui est cohérent avec le boost FAQ et dit:

l'opérateur == n'est pas implémentable pour tr1 :: function dans le langage C++, car nous ne disposons pas d'un moyen fiable pour détecter si un type donné T est égal à l'égalité sans assistance utilisateur.

15
Shafik Yaghmour

Vous pouvez réellement le faire fonctionner avec .target:

template<typename T, typename... U>
size_t getAddress(std::function<T(U...)> f) {
    typedef T(fnType)(U...);
    fnType ** fnPointer = f.template target<fnType*>();
    return (size_t) *fnPointer;
}

if (getAddress(f) == getAddress(g)) {...}

(Ref: C++ essayant d'obtenir l'adresse de la fonction d'un std :: function )

13
P i

Vous pouvez essayer de comparer a et b en premier en comparant leurs .target_type() et si ces identificateurs de type de cible sont identiques, vous pouvez comparer leurs .target() pointeurs. Vous pouvez utiliser un type de cible qui ne correspond pas comme un faux début précoce.

6
Preet Kukreti

Sachez que l’égalité des fonctions (décider si deux fonctions ont toujours le même comportement observable) est un problème indécidable en lambda calcul (c’est pourquoi de nombreux langages de programmation interdisent la comparaison de fonctions).

Ainsi, même si le test == est compilé, il vérifie tout au plus que le code est identique (a la même adresse), mais pas que les fonctions comparées ont le même comportement.

1

Si std::function<T(U...)> f est une fonction membre, fnPointer sera null.

1
yksten