OVH Cloud OVH Cloud

value_type d'un back_inserter

9 réponses
Avatar
s.paris
Bonjour,

Je cherche a connaitre le type de la valeur pointee par un iterateur
de type 'T'. Pour cela, j'utilise 'iterator_traits<T>::value_type'.

Cette methode echoue avec un 'back_inserter' car a priori, celui-ci ne
definit pas le type 'value_type' ni ne surcharge la definition de
'iterator_traits'. Par consequent, 'iterator_traits<T>::value_type'
renvoie le type 'void'.

J'ai cherche sur le web mais je n'ai rien trouve. Ai-je fait une
erreur (oubli d'un include) ?

Je suis sous Linux avec gcc 3.2.2.

Cordialement,

Sylvain

9 réponses

Avatar
Yannick Le goc
Sylvain Paris wrote:
Bonjour,

Je cherche a connaitre le type de la valeur pointee par un iterateur
de type 'T'. Pour cela, j'utilise 'iterator_traits<T>::value_type'.

Cette methode echoue avec un 'back_inserter' car a priori, celui-ci ne
definit pas le type 'value_type' ni ne surcharge la definition de
'iterator_traits'. Par consequent, 'iterator_traits<T>::value_type'
renvoie le type 'void'.

J'ai cherche sur le web mais je n'ai rien trouve. Ai-je fait une
erreur (oubli d'un include) ?

Je suis sous Linux avec gcc 3.2.2.

Cordialement,

Sylvain


Si j'ai bien compris:

J'ai regarde et en effet il n'y a rien de predefini. Le pb avec
back_insert_iterator, c'est qu'il est parametre par un container qui lui
peut etre n'importe quoi (un vector<int> comme map<const char *,
float>), ce qui fait que la STL ne peut definir par defaut un value_type.

Personnellement je ferais un patch du genre:

#include <iterator>

namespace std {

template<typename T, template<typename Elem> class Container>
struct iterator_traits<back_insert_iterator<Container<T> > >
{
typedef T value_type;
// autres typedefs a definir si besoin
};

}

C'est la specialisation partielle de iterator_traits pour
back_insert_iterator prenant en parametre template une classe template
Container ayant un seul parametre template (un peu dur a prononcer)

Ainsi iterator_traits<back_insert_iterator<vector<int> > >::value_type
sera bien int.
En revanche iterator_traits<back_insert_iterator<map<int, unsigned int>
::value_type sera toujours void, la specialisation precedemment
definie ne s'appliquant pas a map, classe prenant au moins 2 parametres


template.

Yannick


Avatar
Loïc Joly
Sylvain Paris wrote:
Bonjour,

Je cherche a connaitre le type de la valeur pointee par un iterateur
de type 'T'. Pour cela, j'utilise 'iterator_traits<T>::value_type'.

Cette methode echoue avec un 'back_inserter' car a priori, celui-ci ne
definit pas le type 'value_type' ni ne surcharge la definition de
'iterator_traits'. Par consequent, 'iterator_traits<T>::value_type'
renvoie le type 'void'.

J'ai cherche sur le web mais je n'ai rien trouve. Ai-je fait une
erreur (oubli d'un include) ?


To implement algorithms only in terms of iterators, it is often
necessary to determine the value and difference types that correspond to
a particular iterator type. Accordingly, it is required that if Iterator
is the type of an iterator, the types

iterator_traits<Iterator>::difference_type
iterator_traits<Iterator>::value_type
iterator_traits<Iterator>::iterator_category

be defined as the iterator’s difference type, value type and iterator
category, respectively. In the case of an output iterator, the types

iterator_traits<Iterator>::difference_type
iterator_traits<Iterator>::value_type

are both defined as void.

Un back_inserter étant un output_iterator, il n'a pas de value_type.
Pourquoi ? Peut-être pour éviter que l'on puisse croire pouvoir lire la
valeur pointée par un output_iterator, on déclare qu'elle est de type void.

--
Loïc

Avatar
s.paris
Loïc Joly wrote in message
[...]
Un back_inserter étant un output_iterator, il n'a pas de value_type.
Pourquoi ? Peut-être pour éviter que l'on puisse croire pouvoir lire la
valeur pointée par un output_iterator, on déclare qu'elle est de type void.



Merci beaucoup. Du coup, je peux reformuler ma question.

Je veux creer une fonction qui utilise un 'output_iterator' (qui peut
etre un 'back_inserter'). Cette fonction a besoin de faire des
conversions de type vers le "pseudo" 'value_type' du dit iterateur.
Est-ce possible de le faire simplement ?

Pour l'instant, j'ai une solution similaire a ce que propose Yannick
(cf. message precedent). Mais ca ne semble pas approprie au vu de la
norme. Je vois une solution qui serait d'utiliser une fonction
'template' qui prendrait toutes les variables en parametre, leurs
types etant obtenus via le mecanisme de 'template'. Mais ca me semble
assez lourd.

Sylvain

Avatar
kanze
Loïc Joly wrote in message
news:<c0bahh$lsh$...

[...]
Un back_inserter étant un output_iterator, il n'a pas de value_type.
Pourquoi ? Peut-être pour éviter que l'on puisse croire pouvoir lire
la valeur pointée par un output_iterator, on déclare qu'elle est de
type void.


La vrai question, je crois, c'est qu'est-ce que tu pourrais faire avec
le type. Comme John Potter a rémarqué, un « output iterator », ce n'est
pas vraiment un itérateur, dans le sens qu'il ne permet pas de
« visiter » un objet ; c'est simplement un « sink » (écoulement ?).

(C'est curieux, je trouve, que le texte le plus important à cet égard,
§24.1.2/2, n'est qu'une note, et donc, officiellement, n'est pas
normatif.)

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
kanze
(Sylvain Paris) wrote in message
news:...
Loïc Joly wrote in message
[...]
Un back_inserter étant un output_iterator, il n'a pas de value_type.
Pourquoi ? Peut-être pour éviter que l'on puisse croire pouvoir lire
la valeur pointée par un output_iterator, on déclare qu'elle est de
type void.


Merci beaucoup. Du coup, je peux reformuler ma question.

Je veux creer une fonction qui utilise un 'output_iterator' (qui peut
etre un 'back_inserter'). Cette fonction a besoin de faire des
conversions de type vers le "pseudo" 'value_type' du dit iterateur.


Pourquoi ? Explique-nous le vrai problème, et peut-être on pourrait en
trouver une solution.

Est-ce possible de le faire simplement ?


Il n'est pas possible à savoir le value_type d'un itérateur de sortie,
parce que n'étant pas vraiment un itérateur, il n'en a pas.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


Avatar
s.paris
Bonjour,


wrote in message
[...]
Je veux creer une fonction qui utilise un 'output_iterator' (qui peut
etre un 'back_inserter'). Cette fonction a besoin de faire des
conversions de type vers le "pseudo" 'value_type' du dit iterateur.


Pourquoi ? Explique-nous le vrai problème, et peut-être on pourrait en
trouver une solution.



En bref:

(a) L'objectif est de convertir des valeurs qui sont donnees a travers
leur representation en chaine de caracteres. Par exemple, on a en
entree "10" et "117" (de type 'std::string') et on veut en sortie 10
et 117 (de type 'int').

(b) En pratique, il y a un cas ou la destination des dites valeurs
peut-etre un conteneur quelconque. On accede a ce conteneur via un
iterateur dont le type est un parametre 'template' de la fonction.
Ainsi, par exemple, si on manipule un 'std::vector v', on peut soit
lui donner la bonne dimension (si on la connait) et passer 'v.begin()'
comme iterateur; soit garder 'v' tel quel et passer 'back_inserter(v)'
comme iterateur pour ajouter les valeurs a la fin de 'v'.

(c) D'ou le probleme suivant: quel est le type pointe par un iterateur
(qui peut etre un 'back_inserter') ? On en a besoin pour le point (a)
dans le cas decrit en (b).

J'espere etre clair. Si ce n'est pas le cas, dites-moi ou ca coince,
je detaillerai plus.

Sylvain


Avatar
kanze
(Sylvain Paris) wrote in message
news:...

wrote in message
[...]
Je veux creer une fonction qui utilise un 'output_iterator' (qui
peut etre un 'back_inserter'). Cette fonction a besoin de faire
des conversions de type vers le "pseudo" 'value_type' du dit
iterateur.


Pourquoi ? Explique-nous le vrai problème, et peut-être on pourrait
en trouver une solution.


En bref:

(a) L'objectif est de convertir des valeurs qui sont donnees a travers
leur representation en chaine de caracteres. Par exemple, on a en
entree "10" et "117" (de type 'std::string') et on veut en sortie 10
et 117 (de type 'int').

(b) En pratique, il y a un cas ou la destination des dites valeurs
peut-etre un conteneur quelconque. On accede a ce conteneur via un
iterateur dont le type est un parametre 'template' de la fonction.
Ainsi, par exemple, si on manipule un 'std::vector v', on peut soit
lui donner la bonne dimension (si on la connait) et passer 'v.begin()'
comme iterateur; soit garder 'v' tel quel et passer 'back_inserter(v)'
comme iterateur pour ajouter les valeurs a la fin de 'v'.

(c) D'ou le probleme suivant: quel est le type pointe par un iterateur
(qui peut etre un 'back_inserter') ? On en a besoin pour le point (a)
dans le cas decrit en (b).

J'espere etre clair. Si ce n'est pas le cas, dites-moi ou ca coince,
je detaillerai plus.


J'ai compris, et je n'ai pas de solution facile. Le problème, c'est que
« output iterator » est une abstraction un peu trop loin de ce dont tu
as besoin. (Mais en fait, je ne sais pas pourquoi un « output iterator »
n'a pas de value_type. C'est vrai que *iter ne fonctionne pas du tout
comme une valeur, mais dans tous les cas, il y a bien un type cible
quand même.) Le mieux que je pourrais te proposer, c'est soit
d'implémenter une version de la fonction qui prend la collection, et
invoque back_inserter lui-même, ou d'exiger à ce que l'utilisateur donne
le type, du genre :

convertir< int >( source.begin(), source.end(), back_inserter( c ) ) ;

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16



Avatar
s.paris
Bonjour,

Loïc Joly wrote in message
Un back_inserter étant un output_iterator, il n'a pas de value_type.
Pourquoi ? Peut-être pour éviter que l'on puisse croire pouvoir lire la
valeur pointée par un output_iterator, on déclare qu'elle est de type void.



En fouillant un peu sur le web pour mieux comprendre mon probleme,
j'ai trouve sur cette page:
http://www.sgi.com/tech/stl/OutputIterator.html une explication
interessante (copie en fin de message).

Il me semble que la notion 'output iterator' est defini "en pensant
fortement" a un 'ostream_iterator' : l'iterateur est capable de
recevoir "en natif" plusieurs types differents. Malheureusement, il me
semble que dans d'autres cas (dont les 'insert iterator') l'iterateur
ne peut manipuler qu'un seul type et que pour ceux-ci la definition de
'value_type' a 'void' est moins justifiee.

Voila le resultat de mes recherches recentes. Je m'achemine donc vers
la definition de quelque chose du type "my_iterator_traits" pour
obtenir le 'value_type' y compris avec un 'back_inserter'.

Sylvain

--

Other iterator types, including Trivial Iterator and Input Iterator,
define the notion of a value type, the type returned when an iterator
is dereferenced. This notion does not apply to Output Iterators,
however, since the dereference operator (unary operator*) does not
return a usable value for Output Iterators. The only context in which
the dereference operator may be used is assignment through an output
iterator: *x = t. Although Input Iterators and output iterators are
roughly symmetrical concepts, there is an important sense in which
accessing and storing values are not symmetrical: for an Input
Iterator operator* must return a unique type, but, for an Output
Iterator, in the expression *x = t, there is no reason why operator must take a unique type. [5] Consequently, there need not be any
unique "value type" for Output Iterators.

Avatar
s.paris
Bonjour,


wrote in message:
[...]
J'ai compris, et je n'ai pas de solution facile. Le problème, c'est que
« output iterator » est une abstraction un peu trop loin de ce dont tu
as besoin. (Mais en fait, je ne sais pas pourquoi un « output iterator »
n'a pas de value_type. C'est vrai que *iter ne fonctionne pas du tout
comme une valeur, mais dans tous les cas, il y a bien un type cible
quand même.) Le mieux que je pourrais te proposer, c'est soit
d'implémenter une version de la fonction qui prend la collection, et
invoque back_inserter lui-même, ou d'exiger à ce que l'utilisateur donne
le type, du genre :

convertir< int >( source.begin(), source.end(), back_inserter( c ) ) ;



Merci beaucoup pour les conseils. En fait, cette syntaxe est celle que
je voulais eviter car avec 'int' ca reste lisible mais ca devient vite
confus. Je pense que je vais me tourner vers un 'traits' specialise. A
priori, il suffit d'utiliser le 'value_type' de l'iterateur dans la
plupart des cas. Pour les 'back_insert_iterator' et equivalent, le
'container_type' fournira le 'value_type' que je cherche.

En tout cas merci pour m'avoir aide a cerner le probleme,

Sylvain