OVH Cloud OVH Cloud

Faire un find sélectif

6 réponses
Avatar
Loïc Joly
Bonjour,

Je souhaiterais faire un find un peu diff=E9rent de std::find : Pour les
s=E9quences, il se comporterait comme std::find, pour les conteneurs
associatifs, il utiliserait le fonction Conteneur::find pour rechercher
la clef uniquement.

Voyez-vous un moyen de faire =E7a sans devoir d=E9finir des surcharges
pour tous les types de conteneurs ? J'ai regard=E9 du c=F4t=E9 des
iterator_traits, mais je n'ai pas l'impression qu'ils aient cette
info... Le plus proche que j'ai pour l'instant, ce serait de regarder
si le value_type de l'iterator_traits est un std::pair, mais ce n'est
qu'une approximation de ce que je recherche.

Une autre id=E9e ?

Merci,

--=20
Lo=EFc

6 réponses

Avatar
Fabien LE LEZ
On 12 Jun 2006 07:30:34 -0700, "Loïc Joly"
:

Je souhaiterais faire un find un peu différent de std::find : Pour les
séquences, il se comporterait comme std::find, pour les conteneurs
associatifs, il utiliserait le fonction Conteneur::find pour rechercher
la clef uniquement.


En gros, tu voudrais un

template <class Conteneur, class MachinAChercher>
Conteneur::iterator MonFind (Conteneur& c, MachinAChercher const& m)
{
if (la_fonction_existe (Conteneur::find))
return c.find (m);
else
return std::find (c.begin(), c.end(), m);
}

C'est bien ça ?

Avatar
James Kanze
Loïc Joly wrote:

Je souhaiterais faire un find un peu différent de std::find :
Pour les séquences, il se comporterait comme std::find, pour
les conteneurs associatifs, il utiliserait le fonction
Conteneur::find pour rechercher la clef uniquement.


Voyez-vous un moyen de faire ça sans devoir définir des
surcharges pour tous les types de conteneurs ? J'ai regardé du
côté des iterator_traits, mais je n'ai pas l'impression qu'ils
aient cette info... Le plus proche que j'ai pour l'instant, ce
serait de regarder si le value_type de l'iterator_traits est
un std::pair, mais ce n'est qu'une approximation de ce que je
recherche.


Une autre idée ?


Dans la bibliothèque Boost, il y a bien un outil de
métaprogrammation qui permet à savoir si une classe à une
fonction member d'un nom donné (ou d'une signature donnée, je ne
suis pas sûr -- et je ne sais pas comment il interagit avec des
templates membre). Est-ce que ça ne ferait pas ton affaire ?

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

Avatar
Pierre Barbier de Reuille
James Kanze wrote:
Loïc Joly wrote:

Je souhaiterais faire un find un peu différent de std::find :
Pour les séquences, il se comporterait comme std::find, pour
les conteneurs associatifs, il utiliserait le fonction
Conteneur::find pour rechercher la clef uniquement.

Voyez-vous un moyen de faire ça sans devoir définir des
surcharges pour tous les types de conteneurs ? J'ai regardé du
côté des iterator_traits, mais je n'ai pas l'impression qu'ils
aient cette info... Le plus proche que j'ai pour l'instant, ce
serait de regarder si le value_type de l'iterator_traits est
un std::pair, mais ce n'est qu'une approximation de ce que je
recherche.

Une autre idée ?


Dans la bibliothèque Boost, il y a bien un outil de
métaprogrammation qui permet à savoir si une classe à une
fonction member d'un nom donné (ou d'une signature donnée, je ne
suis pas sûr -- et je ne sais pas comment il interagit avec des
templates membre). Est-ce que ça ne ferait pas ton affaire ?



En utilisant Boost, une bonne option est d'utiliser la bibliothèque
"iterators", qui contient notamment "transform_iterator", qui permet de
faire un iterateur qui ne sort que le premier élément d'une pair par
exemple.

Pierre


Avatar
Loïc Joly

Dans la bibliothèque Boost, il y a bien un outil de
métaprogrammation qui permet à savoir si une classe à une
fonction member d'un nom donné (ou d'une signature donnée, je ne
suis pas sûr -- et je ne sais pas comment il interagit avec des
templates membre). Est-ce que ça ne ferait pas ton affaire ?


Si probablement, mais je ne l'ai pas trouvé. J'ai cherché
principalement dans TypeTraits, tu pensais à un truc là-dedans ?

--
Loïc

Avatar
Loïc Joly


En utilisant Boost, une bonne option est d'utiliser la bibliothèque
"iterators", qui contient notamment "transform_iterator", qui permet de
faire un iterateur qui ne sort que le premier élément d'une pair par
exemple.


Tiens, je ne la connaissait pas celle là... Je vais y jeter un oeil,
ça a l'air sympa.

Merci

--
Loïc

Avatar
kanze
Loïc Joly wrote:

Dans la bibliothèque Boost, il y a bien un outil de
métaprogrammation qui permet à savoir si une classe à une
fonction member d'un nom donné (ou d'une signature donnée, je ne
suis pas sûr -- et je ne sais pas comment il interagit avec des
templates membre). Est-ce que ça ne ferait pas ton affaire ?


Si probablement, mais je ne l'ai pas trouvé. J'ai cherché
principalement dans TypeTraits, tu pensais à un truc
là-dedans ?


Moi non plus. (Je n'ai cherché qu'après avoir poster, a propos
d'un autre problème.) Il me semble avoir lu quelque part d'une
technique pour déterminer si une classe contenait une fonction
membre ou non, mais je ne me rappelle plus du tout comment, et
je n'arrive plus à le retrouver.

Une recherche dans Google groups pour « has member function C++
meta-programming » donne comme deuxième réponse l'article
. Sa suggestion, adaptée à
ton cas, donne quelque chose comme :

template< typename Container, typename Target >
class InContainerFinder
{
typedef typename Container::const_iterator
Iter ;
template< typename T, Iter (T::*f)( Target const& ) const =
&T::find >
struct Discriminator {} ;

template< typename T >
Iter doFind( Container const& c,
Target const& t,
Discriminator<T> const* ) const
{
return c.find( t ) ;
}

template< typename T >
Iter doFind( Container const& c,
Target const& t,
... ) const
{
return std::find( c.begin(), c.end(), t ) ;
}

public:
Iter find( Container const& c, Target const& t )
const
{
return this->doFind< Container >( c, t, 0 ) ;
}
} ;

template< typename Container, typename Key >
typename Container::const_iterator
find(
Container const& c,
Key const& k )
{
return InContainerFinder< Container, Key >().find( c, k ) ;
}

(C'est probablement possible de le simplifier, mais je me suis
contenté de la transcription la plus directe. Et il faut bien un
compilateur vraiment à jour pour le faire, je crois -- mais ça
marche avec g++ 4.0.2.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34