Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Ivan Vecerina
Bonsoir, "Thomas Labourdette" wrote in message news: | J'ai un problème dans le code suivant avec la ligne | 'while(rit!=s.rend())' | | #include <string> | | int main() | { | std::string s("test"); | std::string::const_reverse_iterator rit=s.rbegin(); | while(rit!=s.rend()) | ++rit; | } | | g++ (version 3.3.2) me renvoie l'erreur suivante : | test_revers_it.cpp:7: error: no match for 'operator!=' in 'rit ! | std::basic_string<_CharT, _Traits, _Alloc>::rend() [with _CharT = char, | _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]()' | | Avec les itérateurs cela fonctionne. Quand est-il pour les | reverse_iterator ? Juste pour clarifier (pas sur si tu en est conscient, vu que ton post ne fournit pas de détails), le code va compiler si l'une des modifs suivantes est faite pour qu'il y ait correspondance des const: std::string const s("test"); // ajout const std::string::const_reverse_iterator rit=s.rbegin(); while(rit!=s.rend()) ++rit; ou: std::string s("test"); std::string::reverse_iterator rit=s.rbegin(); // enleve const while(rit!=s.rend()) ++rit;
Le fait que le code original ne compile pas est conforme au standard C++ de 1998, car seule la fonction d'égalité suivante est définie pour les reverse_iterator: template <class Iterator> bool operator==( const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y);
C'est donc bien une limitation de la librairie standard telle qu'elle a été définie...
Salutations, Ivan -- http://ivan.vecerina.com
Bonsoir,
"Thomas Labourdette" <thomas.labourdette@9online.fr> wrote in message
news:q1ve91-nei.ln1@laptop.labourdette.homelinux.com...
| J'ai un problème dans le code suivant avec la ligne
| 'while(rit!=s.rend())'
|
| #include <string>
|
| int main()
| {
| std::string s("test");
| std::string::const_reverse_iterator rit=s.rbegin();
| while(rit!=s.rend())
| ++rit;
| }
|
| g++ (version 3.3.2) me renvoie l'erreur suivante :
| test_revers_it.cpp:7: error: no match for 'operator!=' in 'rit ! | std::basic_string<_CharT, _Traits, _Alloc>::rend() [with _CharT = char,
| _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]()'
|
| Avec les itérateurs cela fonctionne. Quand est-il pour les
| reverse_iterator ?
Juste pour clarifier (pas sur si tu en est conscient, vu que ton
post ne fournit pas de détails), le code va compiler si l'une des
modifs suivantes est faite pour qu'il y ait correspondance des const:
std::string const s("test"); // ajout const
std::string::const_reverse_iterator rit=s.rbegin();
while(rit!=s.rend())
++rit;
ou:
std::string s("test");
std::string::reverse_iterator rit=s.rbegin(); // enleve const
while(rit!=s.rend())
++rit;
Le fait que le code original ne compile pas est conforme au
standard C++ de 1998, car seule la fonction d'égalité suivante
est définie pour les reverse_iterator:
template <class Iterator>
bool operator==(
const reverse_iterator<Iterator>& x,
const reverse_iterator<Iterator>& y);
C'est donc bien une limitation de la librairie standard telle
qu'elle a été définie...
Bonsoir, "Thomas Labourdette" wrote in message news: | J'ai un problème dans le code suivant avec la ligne | 'while(rit!=s.rend())' | | #include <string> | | int main() | { | std::string s("test"); | std::string::const_reverse_iterator rit=s.rbegin(); | while(rit!=s.rend()) | ++rit; | } | | g++ (version 3.3.2) me renvoie l'erreur suivante : | test_revers_it.cpp:7: error: no match for 'operator!=' in 'rit ! | std::basic_string<_CharT, _Traits, _Alloc>::rend() [with _CharT = char, | _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]()' | | Avec les itérateurs cela fonctionne. Quand est-il pour les | reverse_iterator ? Juste pour clarifier (pas sur si tu en est conscient, vu que ton post ne fournit pas de détails), le code va compiler si l'une des modifs suivantes est faite pour qu'il y ait correspondance des const: std::string const s("test"); // ajout const std::string::const_reverse_iterator rit=s.rbegin(); while(rit!=s.rend()) ++rit; ou: std::string s("test"); std::string::reverse_iterator rit=s.rbegin(); // enleve const while(rit!=s.rend()) ++rit;
Le fait que le code original ne compile pas est conforme au standard C++ de 1998, car seule la fonction d'égalité suivante est définie pour les reverse_iterator: template <class Iterator> bool operator==( const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y);
C'est donc bien une limitation de la librairie standard telle qu'elle a été définie...
Salutations, Ivan -- http://ivan.vecerina.com
Thomas Labourdette
Bonsoir, "Thomas Labourdette" wrote in message news: | #include <string> | | int main() | { | std::string s("test"); | std::string::const_reverse_iterator rit=s.rbegin(); | while(rit!=s.rend()) | ++rit; | } | [...]
Juste pour clarifier (pas sur si tu en est conscient, vu que ton post ne fournit pas de détails), le code va compiler si l'une des modifs suivantes est faite pour qu'il y ait correspondance des const: std::string const s("test"); // ajout const std::string::const_reverse_iterator rit=s.rbegin(); while(rit!=s.rend()) ++rit; Merci c'est bien ça.
Le fait que le code original ne compile pas est conforme au standard C++ de 1998, car seule la fonction d'égalité suivante est définie pour les reverse_iterator: template <class Iterator> bool operator==( const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y);
Qu'elle est la raison de cette différence entre les iterator et les reverse_iterator ?
Juste pour clarifier (pas sur si tu en est conscient, vu que ton
post ne fournit pas de détails), le code va compiler si l'une des
modifs suivantes est faite pour qu'il y ait correspondance des const:
std::string const s("test"); // ajout const
std::string::const_reverse_iterator rit=s.rbegin();
while(rit!=s.rend())
++rit;
Merci c'est bien ça.
Le fait que le code original ne compile pas est conforme au
standard C++ de 1998, car seule la fonction d'égalité suivante
est définie pour les reverse_iterator:
template <class Iterator>
bool operator==(
const reverse_iterator<Iterator>& x,
const reverse_iterator<Iterator>& y);
Qu'elle est la raison de cette différence entre les iterator et les
reverse_iterator ?
Bonsoir, "Thomas Labourdette" wrote in message news: | #include <string> | | int main() | { | std::string s("test"); | std::string::const_reverse_iterator rit=s.rbegin(); | while(rit!=s.rend()) | ++rit; | } | [...]
Juste pour clarifier (pas sur si tu en est conscient, vu que ton post ne fournit pas de détails), le code va compiler si l'une des modifs suivantes est faite pour qu'il y ait correspondance des const: std::string const s("test"); // ajout const std::string::const_reverse_iterator rit=s.rbegin(); while(rit!=s.rend()) ++rit; Merci c'est bien ça.
Le fait que le code original ne compile pas est conforme au standard C++ de 1998, car seule la fonction d'égalité suivante est définie pour les reverse_iterator: template <class Iterator> bool operator==( const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y);
Qu'elle est la raison de cette différence entre les iterator et les reverse_iterator ?
@+ -- Thomas Labourdette
Ivan Vecerina
"Thomas Labourdette" wrote in message news: | Qu'elle est la raison de cette différence entre les iterator et les | reverse_iterator ? std::string::iterator est défini comme étant convertible en std::string::const_iterator (ce qui est le cas pour toutes les collections standard). Du coup, lors d'une comparaison hybride, l'iterator est implicitement converti en const_iterator, et l'opérateur s'appliquant à 2 const_iterators est invoqué.
Les reverse_iterator sont indirectement implémentés à l'aide d'un template: typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
Le problème est que la comparaison des reverse_iterator a été définie comme: template <class Iterator> bool operator==( const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y) { return x.base()==y.base(); } // impl typique
Il existe bien un template-constructeur pour effectuer une converstions entre reverse_iterators compatibles, mais cela va au-delà des limites imposées au compilateurs pour la recherche de conversions implicites (serait dangereux, surtout avec des templates). Là est la question: il faut choisir une limite aux conversions automatique et à la flexibilité que l'on donne. Les conversions automatiques sont pratiques, mais souvent aussi dangereuses.
Il eût en effet été possible de définir, en lieu et place de l'opération précédente: template<class A, class B> bool operator==( const reverse_iterator<A>& x, const reverse_iterator<B>& y) { return x.base()==y.base(); } Ce qui aurait rendu le code original légal.
A noter, une 3ème alternative pour que ce premier code compile: std::string s("test"); std::string::const_reverse_iterator rit=s.rbegin(); // enleve const while(rit.base()!=s.rend().base()) ++rit; Parce qu'il est défini que les reverse-iterators sont implémentés à l'aide du template std::reverse_iterator<T>, il est possible de faire appel fonctions membres de celui-ci... (lorsque les autres alternatives ne sont pas pratiques).
Amicalement, Ivan -- http://ivan.vecerina.com
"Thomas Labourdette" <thomas.labourdette@9online.fr> wrote in message
news:8i8f91-i3k.ln1@laptop.labourdette.homelinux.com...
| Qu'elle est la raison de cette différence entre les iterator et les
| reverse_iterator ?
std::string::iterator est défini comme étant convertible
en std::string::const_iterator (ce qui est le cas pour toutes les
collections standard). Du coup, lors d'une comparaison hybride,
l'iterator est implicitement converti en const_iterator,
et l'opérateur s'appliquant à 2 const_iterators est invoqué.
Les reverse_iterator sont indirectement implémentés à l'aide
d'un template:
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
Le problème est que la comparaison des reverse_iterator a été
définie comme:
template <class Iterator>
bool operator==(
const reverse_iterator<Iterator>& x,
const reverse_iterator<Iterator>& y)
{ return x.base()==y.base(); } // impl typique
Il existe bien un template-constructeur pour effectuer une
converstions entre reverse_iterators compatibles, mais cela
va au-delà des limites imposées au compilateurs pour la
recherche de conversions implicites (serait dangereux,
surtout avec des templates).
Là est la question: il faut choisir une limite aux conversions
automatique et à la flexibilité que l'on donne. Les conversions
automatiques sont pratiques, mais souvent aussi dangereuses.
Il eût en effet été possible de définir, en lieu et place de
l'opération précédente:
template<class A, class B>
bool operator==(
const reverse_iterator<A>& x,
const reverse_iterator<B>& y)
{ return x.base()==y.base(); }
Ce qui aurait rendu le code original légal.
A noter, une 3ème alternative pour que ce premier code compile:
std::string s("test");
std::string::const_reverse_iterator rit=s.rbegin(); // enleve const
while(rit.base()!=s.rend().base())
++rit;
Parce qu'il est défini que les reverse-iterators sont
implémentés à l'aide du template std::reverse_iterator<T>,
il est possible de faire appel fonctions membres de celui-ci...
(lorsque les autres alternatives ne sont pas pratiques).
"Thomas Labourdette" wrote in message news: | Qu'elle est la raison de cette différence entre les iterator et les | reverse_iterator ? std::string::iterator est défini comme étant convertible en std::string::const_iterator (ce qui est le cas pour toutes les collections standard). Du coup, lors d'une comparaison hybride, l'iterator est implicitement converti en const_iterator, et l'opérateur s'appliquant à 2 const_iterators est invoqué.
Les reverse_iterator sont indirectement implémentés à l'aide d'un template: typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
Le problème est que la comparaison des reverse_iterator a été définie comme: template <class Iterator> bool operator==( const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y) { return x.base()==y.base(); } // impl typique
Il existe bien un template-constructeur pour effectuer une converstions entre reverse_iterators compatibles, mais cela va au-delà des limites imposées au compilateurs pour la recherche de conversions implicites (serait dangereux, surtout avec des templates). Là est la question: il faut choisir une limite aux conversions automatique et à la flexibilité que l'on donne. Les conversions automatiques sont pratiques, mais souvent aussi dangereuses.
Il eût en effet été possible de définir, en lieu et place de l'opération précédente: template<class A, class B> bool operator==( const reverse_iterator<A>& x, const reverse_iterator<B>& y) { return x.base()==y.base(); } Ce qui aurait rendu le code original légal.
A noter, une 3ème alternative pour que ce premier code compile: std::string s("test"); std::string::const_reverse_iterator rit=s.rbegin(); // enleve const while(rit.base()!=s.rend().base()) ++rit; Parce qu'il est défini que les reverse-iterators sont implémentés à l'aide du template std::reverse_iterator<T>, il est possible de faire appel fonctions membres de celui-ci... (lorsque les autres alternatives ne sont pas pratiques).
Amicalement, Ivan -- http://ivan.vecerina.com
Thomas Labourdette
"Thomas Labourdette" wrote in message news: | Qu'elle est la raison de cette différence entre les iterator et les | reverse_iterator ? std::string::iterator est défini comme étant convertible en std::string::const_iterator (ce qui est le cas pour toutes les collections standard). Du coup, lors d'une comparaison hybride, l'iterator est implicitement converti en const_iterator, et l'opérateur s'appliquant à 2 const_iterators est invoqué. [... explication détaillée ...]
Merci, j'ai bien compris les différences d'implémentation entre iterator et reverse_iterator.
@+ -- Thomas Labourdette
"Thomas Labourdette" <thomas.labourdette@9online.fr> wrote in message
news:8i8f91-i3k.ln1@laptop.labourdette.homelinux.com...
| Qu'elle est la raison de cette différence entre les iterator et les
| reverse_iterator ?
std::string::iterator est défini comme étant convertible
en std::string::const_iterator (ce qui est le cas pour toutes les
collections standard). Du coup, lors d'une comparaison hybride,
l'iterator est implicitement converti en const_iterator,
et l'opérateur s'appliquant à 2 const_iterators est invoqué.
[... explication détaillée ...]
Merci, j'ai bien compris les différences d'implémentation entre
iterator et reverse_iterator.
"Thomas Labourdette" wrote in message news: | Qu'elle est la raison de cette différence entre les iterator et les | reverse_iterator ? std::string::iterator est défini comme étant convertible en std::string::const_iterator (ce qui est le cas pour toutes les collections standard). Du coup, lors d'une comparaison hybride, l'iterator est implicitement converti en const_iterator, et l'opérateur s'appliquant à 2 const_iterators est invoqué. [... explication détaillée ...]
Merci, j'ai bien compris les différences d'implémentation entre iterator et reverse_iterator.
@+ -- Thomas Labourdette
Thomas Labourdette
Encore moi :-)
"Thomas Labourdette" wrote in message news: | Qu'elle est la raison de cette différence entre les iterator et les | reverse_iterator ? std::string::iterator est défini comme étant convertible en std::string::const_iterator (ce qui est le cas pour toutes les collections standard). Du coup, lors d'une comparaison hybride, l'iterator est implicitement converti en const_iterator, et l'opérateur s'appliquant à 2 const_iterators est invoqué.
Les reverse_iterator sont indirectement implémentés à l'aide d'un template: typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
Le problème est que la comparaison des reverse_iterator a été définie comme: template <class Iterator> bool operator==( const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y) { return x.base()==y.base(); } // impl typique
Il existe bien un template-constructeur pour effectuer une converstions entre reverse_iterators compatibles, mais cela va au-delà des limites imposées au compilateurs pour la recherche de conversions implicites (serait dangereux, surtout avec des templates). Là est la question: il faut choisir une limite aux conversions automatique et à la flexibilité que l'on donne. Les conversions automatiques sont pratiques, mais souvent aussi dangereuses.
[...]
Je présume que dans l'exemple ci-dessous, il y a des conversions implicites qui font que la fonction r compile mais qui ne qu'il n'y en a pas dans le test fait dans main() ?
Je pense avoir compris les différences d'implémentation entre les iterator et les reverse_iterator, par contre je ne comprends pas le pourquoi ?
Merci @+ -- Thomas Labourdette
Encore moi :-)
"Thomas Labourdette" <thomas.labourdette@9online.fr> wrote in message
news:8i8f91-i3k.ln1@laptop.labourdette.homelinux.com...
| Qu'elle est la raison de cette différence entre les iterator et les
| reverse_iterator ?
std::string::iterator est défini comme étant convertible
en std::string::const_iterator (ce qui est le cas pour toutes les
collections standard). Du coup, lors d'une comparaison hybride,
l'iterator est implicitement converti en const_iterator,
et l'opérateur s'appliquant à 2 const_iterators est invoqué.
Les reverse_iterator sont indirectement implémentés à l'aide
d'un template:
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
Le problème est que la comparaison des reverse_iterator a été
définie comme:
template <class Iterator>
bool operator==(
const reverse_iterator<Iterator>& x,
const reverse_iterator<Iterator>& y)
{ return x.base()==y.base(); } // impl typique
Il existe bien un template-constructeur pour effectuer une
converstions entre reverse_iterators compatibles, mais cela
va au-delà des limites imposées au compilateurs pour la
recherche de conversions implicites (serait dangereux,
surtout avec des templates).
Là est la question: il faut choisir une limite aux conversions
automatique et à la flexibilité que l'on donne. Les conversions
automatiques sont pratiques, mais souvent aussi dangereuses.
[...]
Je présume que dans l'exemple ci-dessous, il y a des conversions
implicites qui font que la fonction r compile mais qui ne qu'il n'y en
a pas dans le test fait dans main() ?
"Thomas Labourdette" wrote in message news: | Qu'elle est la raison de cette différence entre les iterator et les | reverse_iterator ? std::string::iterator est défini comme étant convertible en std::string::const_iterator (ce qui est le cas pour toutes les collections standard). Du coup, lors d'une comparaison hybride, l'iterator est implicitement converti en const_iterator, et l'opérateur s'appliquant à 2 const_iterators est invoqué.
Les reverse_iterator sont indirectement implémentés à l'aide d'un template: typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
Le problème est que la comparaison des reverse_iterator a été définie comme: template <class Iterator> bool operator==( const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y) { return x.base()==y.base(); } // impl typique
Il existe bien un template-constructeur pour effectuer une converstions entre reverse_iterators compatibles, mais cela va au-delà des limites imposées au compilateurs pour la recherche de conversions implicites (serait dangereux, surtout avec des templates). Là est la question: il faut choisir une limite aux conversions automatique et à la flexibilité que l'on donne. Les conversions automatiques sont pratiques, mais souvent aussi dangereuses.
[...]
Je présume que dans l'exemple ci-dessous, il y a des conversions implicites qui font que la fonction r compile mais qui ne qu'il n'y en a pas dans le test fait dans main() ?
Je pense avoir compris les différences d'implémentation entre les iterator et les reverse_iterator, par contre je ne comprends pas le pourquoi ?
Merci @+ -- Thomas Labourdette
Ivan Vecerina
"Thomas Labourdette" wrote in message news: | Encore moi :-) ... | Je présume que dans l'exemple ci-dessous, il y a des conversions | implicites qui font que la fonction r compile mais qui ne qu'il n'y en | a pas dans le test fait dans main() ? ... | void r(std::string::const_reverse_iterator current, | std::string::const_reverse_iterator end) | { | current!=end; //ok | } ... | std::string s("test"); ... | r(s.rbegin(),s.rend()); Oui, la classe reverse_iterator< > a un template-constructor permettant les conversions implicites: template <class Iterator> class reverse_iterator : .... { .... template <class U> reverse_iterator(const reverse_iterator<U>& u); .... } Ceci permet l'appel de la fonction r. De même que l'initialisation de rit ci-dessous.
Si la même conversion implicite était appliquée dans cette dernière ligne, elle serait acceptée. Mais le compilateur n'effectuera pas celle-ci implicitement. Vaguement, de mémoire, je pense qu'elle ne sera pas envisagée parce qu'elle requiert deux instantiations de templates (ou qqch du genre): l'operateur != et le constructeur de conversion.
Mais même sans cette limitation, le compilateur ne pourrait pas choisir entre deux conversions possibles, comme ci-dessous:
int main() { std::string s("test"); std::string::const_reverse_iterator rit=s.rbegin(); r( rit ,s.rend()); }
A+, Ivan -- http://ivan.vecerina.com
"Thomas Labourdette" <thomas.labourdette@9online.fr> wrote in message
news:jeig91-fap.ln1@laptop.labourdette.homelinux.com...
| Encore moi :-)
...
| Je présume que dans l'exemple ci-dessous, il y a des conversions
| implicites qui font que la fonction r compile mais qui ne qu'il n'y en
| a pas dans le test fait dans main() ?
...
| void r(std::string::const_reverse_iterator current,
| std::string::const_reverse_iterator end)
| {
| current!=end; //ok
| }
...
| std::string s("test");
...
| r(s.rbegin(),s.rend());
Oui, la classe reverse_iterator< > a un template-constructor
permettant les conversions implicites:
template <class Iterator>
class reverse_iterator : ....
{
....
template <class U> reverse_iterator(const reverse_iterator<U>& u);
....
}
Ceci permet l'appel de la fonction r.
De même que l'initialisation de rit ci-dessous.
Si la même conversion implicite était appliquée dans cette
dernière ligne, elle serait acceptée.
Mais le compilateur n'effectuera pas celle-ci implicitement.
Vaguement, de mémoire, je pense qu'elle ne sera pas envisagée
parce qu'elle requiert deux instantiations de templates
(ou qqch du genre): l'operateur != et le constructeur de conversion.
Mais même sans cette limitation, le compilateur ne pourrait
pas choisir entre deux conversions possibles, comme ci-dessous:
"Thomas Labourdette" wrote in message news: | Encore moi :-) ... | Je présume que dans l'exemple ci-dessous, il y a des conversions | implicites qui font que la fonction r compile mais qui ne qu'il n'y en | a pas dans le test fait dans main() ? ... | void r(std::string::const_reverse_iterator current, | std::string::const_reverse_iterator end) | { | current!=end; //ok | } ... | std::string s("test"); ... | r(s.rbegin(),s.rend()); Oui, la classe reverse_iterator< > a un template-constructor permettant les conversions implicites: template <class Iterator> class reverse_iterator : .... { .... template <class U> reverse_iterator(const reverse_iterator<U>& u); .... } Ceci permet l'appel de la fonction r. De même que l'initialisation de rit ci-dessous.
Si la même conversion implicite était appliquée dans cette dernière ligne, elle serait acceptée. Mais le compilateur n'effectuera pas celle-ci implicitement. Vaguement, de mémoire, je pense qu'elle ne sera pas envisagée parce qu'elle requiert deux instantiations de templates (ou qqch du genre): l'operateur != et le constructeur de conversion.
Mais même sans cette limitation, le compilateur ne pourrait pas choisir entre deux conversions possibles, comme ci-dessous: