127 votes

Que sont les comparateurs transparents?

En C++14, conteneurs associatifs semblent avoir changé depuis C++11 – [associatif.reqmts]/13, dit:

La fonction de membre de modèles d' find, count, lower_bound, upper_bound, et equal_range ne doit pas participer à la résolution de surcharge, à moins que le type Compare::is_transparent existe.

Quel est le but de faire une comparaison "transparent"?

C++14 fournit également des modèles de bibliothèque comme ceci:

template <class T = void> struct less {
    constexpr bool operator()(const T& x, const T& y) const;
    typedef T first_argument_type;
    typedef T second_argument_type;
    typedef bool result_type;
};

template <> struct less<void> {
    template <class T, class U> auto operator()(T&& t, U&& u) const
    -> decltype(std::forward<T>(t) < std::forward<U>(u));
    typedef *unspecified* is_transparent;
};

Ainsi, par exemple, std::set<T, std::less<T>> serait de ne pas avoir un comparateur transparent, mais std::set<T, std::less<>> permettrait d' en avoir un.

Quel problème est-ce à résoudre, et elle le fait de changer la façon dont les conteneurs standard de travail? Par exemple, les paramètres du modèle de std::set sont encore en Key, Compare = std::less<Key>, ..., donc l'ensemble par défaut de perdre son find, count, etc. les membres?

78voto

Jonathan Wakely Points 45593

Quel problème est-ce à résoudre,

Voir Dietmar et remyabel de réponse.

est-ce que changer la façon dont les conteneurs standard de travail?

Non, pas par défaut.

La nouvelle fonction membre template surcharges de find etc. vous permettre d'utiliser un type qui est comparable avec le conteneur de clé, au lieu d'utiliser le type de la clé elle-même. Voir N3465 par Joaquín Mª López Muñoz pour la justification et détaillées, rédigées d'une proposition visant à ajouter cette fonctionnalité.

À la Bristol réunion confiées au groupe de travail est convenu que la hétérogène fonction de recherche est utile et souhaitable, mais nous ne pouvait pas être sûr que Joaquín de la proposition serait en sécurité dans tous les cas. Le N3465 proposition aurait causé de sérieux problèmes pour certains programmes (voir l' Impact sur le code existant de la section). Joaquín préparé une mise à jour du projet de proposition avec certaines implémentations alternatives avec les différents arbitrages, qui a été très utile en aidant confiées au groupe de travail de comprendre les avantages et les inconvénients, mais ils ont tous risquait de briser certains des programmes d'une certaine façon, donc il n'y a pas de consensus pour ajouter la fonctionnalité. Nous avons décidé que, bien qu'il ne serait pas sûr d'ajouter la fonctionnalité sans condition, qu'il serait plus sûr si elle a été désactivée par défaut et uniquement "opt-in".

La différence clé de la N3657 proposition (qui a été la dernière minute de révision par moi-même et STL basé sur N3465 et plus tard inédit projet par Joaquín) a été d'ajouter de l' is_transparent type que le protocole qui peut être utilisé pour activer la nouvelle fonctionnalité.

Si vous n'utilisez pas "transparent foncteur" (c'est à dire celui qui définit un is_transparent type), puis les conteneurs se comportent de la même comme ils l'ont toujours fait, et c'est toujours la valeur par défaut.

Ssi vous choisissez d'utiliser std::less<> (ce qui est nouveau pour le C++14) ou d'une autre "transparent foncteur de type" ensuite, vous obtenez la nouvelle fonctionnalité.

À l'aide de std::less<> est facile avec alias modèles:

template<typename T, typename Cmp = std::less<>, typename Alloc = std::allocator<T>>
  using set = std::set<T, Cmp, Alloc>;

Le nom de l' is_transparent vient de STL N3421 qui a ajouté le "diamant opérateurs" de C++14. Un "transparent foncteur" est celle qui accepte tous les types d'argument (qui n'ont pas à être les mêmes) et de simplement suivre ces arguments d'un autre opérateur. Un tel foncteur se trouve être exactement ce que vous voulez pour hétérogène de recherche dans les conteneurs associatifs, de sorte que le type is_transparent a été ajoutée à toutes les diamants opérateurs et de les utiliser comme type de balise pour indiquer la nouvelle fonctionnalité doit être activée dans les conteneurs associatifs. Techniquement, les conteneurs n'ont pas besoin d'un "transparent foncteur", juste un qui prend en charge l'appel avec des types hétérogènes (par exemple, l' pointer_comp type de http://stackoverflow.com/a/18940595/981959 n'est pas transparent selon STL de la définition de, mais la définition d' pointer_comp::is_transparent lui permet d'être utilisé pour résoudre le problème). Si vous ne jamais rechercher dans votre std::set<T, C> , avec des touches de type T ou int alors C ne doit être appelée avec des arguments de type T et int (dans l'ordre), il n'a pas besoin d'être vraiment transparent. Nous avons utilisé ce nom, en partie parce que nous ne pouvions pas trouver un meilleur nom (j'aurais préféré is_polymorphic , car de tels foncteurs utilisation polymorphisme statique, mais il y a déjà un std::is_polymorphic type de trait qui se réfère à la dynamique de polymorphisme).

36voto

Dietmar Kühl Points 70604

En C++11, il ne sont pas des modèles de membre find(), lower_bound(), etc. C'est, rien n'est perdu par ce changement. Le membre modèles ont été introduits avec n3657 pour permettre hétérogène clés utilisés avec les conteneurs associatifs. Je ne vois pas d'exemple concret où c'est utile, sauf pour l'exemple qui est bon et mauvais!

L' is_transparent utilisation est destiné à éviter les conversions. Si le membre modèles ont été sans contrainte, code existant peut passer à travers les objets directement, ce qui aurait été converti sans que le membre de modèles. L'exemple de cas d'utilisation de n3657 est la localisation d'un objet dans un std::set<std::string> à l'aide d'une chaîne de caractères littérale: avec le C++11 définition d'un std::string objet est construit lors du passage d'une chaîne de caractères littéraux de la fonction correspondante de membre. Avec le changement, il est possible d'utiliser la chaîne de caractères littérale directement. Si le sous-jacent en fonction de comparaison d'objet est mis en œuvre exclusivement en termes de std::string qui est mauvais, parce que maintenant un std::string sera créée pour chaque comparaison. En revanche, si le sous-jacent comparaison de la fonction de l'objet peut prendre un std::string et un littéral de chaîne, d'éviter la construction d'un objet temporaire.

Le sous - is_transparent type dans la fonction de comparaison objet fournit un moyen de spécifier si l'basées sur des modèles de fonction de membre doit être utilisé: si la fonction de comparaison de l'objet peut faire face à une hétérogénéité des arguments, il définit ce type pour indiquer qu'il peut traiter avec des arguments différents de manière efficace. Par exemple, le nouvel opérateur de la fonction des objets délégué operator<() et demande à être transparent. Que, au moins, les travaux de l' std::string qui a surchargé de moins que les opérateurs en char const* comme argument. Depuis ces objets de fonction sont aussi des nouvelles, même si elles font quelque chose de mal (c'est à dire nécessitent une conversion d'un certain type), il serait, au moins, ne pas être en silence, un changement entraînant une dégradation des performances.

7voto

woolstar Points 4229

Stephan T Lavavej parle des problèmes pour lesquels le compilateur continue de créer des temporaires, et comment sa proposition de foncteurs d'opérateurs transparents résoudra ce problème en c ++ 1y

GoingNative 2013 - Ne pas aider le compilateur (environ l'heure)

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