8
votes

Vérifier / modifier Itérateur "Constance"

J'ai deux questions et demi étroitement liées. Compte tenu d'un type d'itérateur STL passé sous forme de paramètre de modèle:

  1. Comment déterminer si le type correspond à un itérateur Const- ou non constitué?
  2. Alternativement à 1., comment imposer (utiliser activer_if s par exemple) que ce type correspond à un itérateur non constitué?
  3. Comment obtenir la version constante de l'itérateur de la non-const une (et vice versa )? [Remarque: répondit dans Ce message ; Sans surprise, vous ne pouvez pas. ]

    D'où vient cette question:

    J'ai écrit une petite classe pour faciliter les opérations arithmétiques / relationnelles / algébriques sur des vecteurs (par vecteur, je veux dire 1D de données de taille fixe, pas les vecteurs STL). Au lieu d'imposer un conteneur de données spécifique, j'ai défini une interface et dérivé plusieurs conteneurs possibles qui sont fondamentalement "emballage" diverses façons de stocker des données. L'un de ces conteneurs est une enveloppe pour les itérateurs de stl-itérateurs et j'ai des problèmes avec elle.


3 commentaires

Vous pouvez commencer par std :: is_concst .


@Bobtfish j'ai essayé mais je ne fonctionne pas. const_itéator et const itérateur sont deux choses différentes. Essayez ceci: Pastebin.com/kkqeqthj


@Bobtfish Désolé, avez-vous modifié votre commentaire? Je pourrais jurer que je n'ai pas vu le déclintype (* it) Quand j'ai posté mon dernier commentaire ... Vous auriez raison aussi avec ceci je suppose :)


3 Réponses :


3
votes

pour 1), vous pouvez faire quelque chose comme ceci: xxx

ou ceci: xxx

Vous pouvez utiliser ces prédicats pour réussir à std :: activer_if à mettre en œuvre 2).

NOTE: Comme indiqué par R. Martinho Fernandes dans les commentaires, ces prédicats échoueront si L'itérateur en question utilise un type différent de celui des références simples pour son référence (tel que std :: vecteur :: const_iterator fait). < / p>


5 commentaires

Merci beaucoup! Je suppose que vous avez été d'abord à poster la réponse et @andyProwl a la même réponse que vous, donc je ne sais pas lequel pour marquer .. Juste une question: Pourquoi utiliser déclinger ?


@ Sh3ljohn * itérateur est une expression , mais std :: retirer_reference nécessite un type (car c'est un modèle avec un paramètre de type de modèle). Par conséquent, vous devez en quelque sorte obtenir le type de l'expression - et c'est ce que déclinger est pour.


Et si déclinger (* itérateur) est un proxy et non une référence?


@ R.martinhofernandes: vous voulez dire comme vecteur :: itérateur ? ( frighder )


@ R.martinhofernandes puis vous n'avez pas de chance avec cette approche. Bonne prise.



6
votes

question 1: strong>

Vous pouvez utiliser le type de type suivant: p> xxx pré>

Voici une démonstration: p>

int main()
{
    std::vector<int> v;
    foo(v.begin()); // OK
    foo(v.cbegin()); // ERROR!
}


6 commentaires

Je pensais simplement à utiliser le :: Référence Typef des traits de type The Type Trop .. Mais votre réponse est impeccable! Merci :)


@ Sh3ljohn: content que cela ait aidé :)


Juste une question: pourquoi ne pas utiliser typename = tyname stdd :: activer_if :: Valeur> :: Type comme "Modèle-filtre" dans votre exemple pour la question 2? C'est le moyen d'utiliser Activer_ifs que j'ai vu le plus souvent, mais s'il y a quelque chose qui ne va pas avec ça, j'aimerais savoir quoi :)


@ Sh3ljohn voir FlamingDangerzone.com/cxx11/2012/06 / 01 / ... pour une explication de la manière dont ce formulaire peut échouer.


@ Sh3ljohn: Désolé, je devais partir hier et vu votre commentaire que maintenant. Fondamentalement, R.Martinhofernandes vous a donné la réponse;)


@ R.martinhofernandes: (Merci pour cela)



2
votes

Vous pouvez utiliser SFIAE sur

decltype( *declval<T&>() = std::move(*declval<T&>()) )


9 commentaires

Pour l'amour de tout, Utilisez * std :: déclval () .


@Xeo: Pourquoi? Il s'agit d'environ 20 caractères supplémentaires pour quel avantage?


L'avantage est pour l'amour de tout


Eh bien, je n'aime pas tout. Certaines choses (ou idées) sont trop horribles pour aimer.


Cela ne conduit pas à la fausse pensée de Nullpointer-Dereferencing (même si cela ne se produit pas réellement), est beaucoup plus clair et les gens sauront ce qu'il fait.


@Xeo: Les personnes qui ne comprennent pas «contexte inévalué», ne comprennent certainement pas Sfinae.


@Benvoigt: Cela rendrait la contrainte Sfinae un peu plus compliquée cependant, n'est-ce pas? (Je veux dire, peu importe si std :: déclval est utilisé ou non)


@Andy: Mon point est que le test demandé dans la question est inutile pour tout algorithme réel. Avez-vous besoin d'attribuer? Concevoir un test Sfinae. Appelez une fonction de membre non-Const? Utilisez Sfinae sur cela. Il suffit d'avoir un itérateur qui n'est pas un const_iterator ne rend pas nécessairement le travail d'algorithme.


OK, je préfère honnêtement une contrainte du type " Je veux quelque chose qui satisfait aux exigences de ce concept " plutôt que " Je veux que quelque chose qui me permet de faire cela et cette opération ", mais je suppose que c'est une question de goût