OVH Cloud OVH Cloud

Sélectionner un attribut au run-time

1 réponse
Avatar
sebacote
Bonjour,

Considérez le code suivant:

struct Point
{
Point( int x, int y ) : _x( x ), _y( y ) {}
int GetX() const { return _x; }
int GetY() const { return _y; }
int _x, _y;
};

template <typename T>
struct Container
{
typedef std::vector<T> Cltn_t;
Cltn_t _cltn;

template <typename R>
T* Get( const R& value, R ( T::*pfn )() const )
{
for ( size_t idx = 0; idx < _cltn.size(); ++idx )
if ( ( _cltn[idx].*pfn )() == value )
return &_cltn[idx];

return static_cast<T*>( 0 );
}
};

int main()
{
Container<Point> cont;
cont._cltn.push_back( Point( 10, 10 ) );
cont._cltn.push_back( Point( 20, 20 ) );

Point* p = cont.Get( 10, &Point::GetX );
p = cont.Get( 20, &Point::GetX );
p = cont.Get( 30, &Point::GetX );

return 0;
}

Dans le cas réel, je dois travailler avec des structures C qui n'ont
pas de fonctions membres. Est-il possible d'utiliser une astuce basée
sur les "templates" afin de sélectionner au "run-time" la variable
membre que l'on veut utiliser pour faire la comparaison?

Je sais qu'il existe des solutions, comme définir un "functor", passer
un "callback", dériver une classe, etc, mais j'aimerais éviter d'avoir
à écrire du code spécifique à chaque utilisation.

Exemple de ce que j'aimerais faire (je sais que ce n'est pas du code
C++ valide, c'est juste pour donner une idée de ce que j'ai en tête!)

struct Point
{
int _x, _y;
};

template <typename T>
struct Container
{
typedef std::vector<T> Cltn_t;
Cltn_t _cltn;

template <typename R>
T* Get( const R& value, T::*R member ) /* !!! */
{
for ( size_t idx = 0; idx < _cltn.size(); ++idx )
if ( _cltn[idx].*member == value ) /* !!! */
return &_cltn[idx];

return static_cast<T*>( 0 );
}
};

int main()
{
Point pt;
pt._x = 10;
pt._y = 20;
Container<Point> cont;
cont._cltn.push_back( pt );

Point* p = cont.Get( 10, &Point::_x ); /* !!! */

return 0;
}

1 réponse

Avatar
Loïc Joly
S?bastien C?t? wrote:

Dans le cas réel, je dois travailler avec des structures C qui n'ont
pas de fonctions membres. Est-il possible d'utiliser une astuce basée
sur les "templates" afin de sélectionner au "run-time" la variable
membre que l'on veut utiliser pour faire la comparaison?

Je sais qu'il existe des solutions, comme définir un "functor", passer
un "callback", dériver une classe, etc, mais j'aimerais éviter d'avoir
à écrire du code spécifique à chaque utilisation.

Exemple de ce que j'aimerais faire (je sais que ce n'est pas du code
C++ valide, c'est juste pour donner une idée de ce que j'ai en tête!)


Bin, je me demande si en fait ce que tu souhaites faire n'est pas du
code C++ valide à la syntaxe près dans la déclaration de fonction.

Je n'ai jamais utilisé ça, donc je dit peut-être une bétise, mais j'ai
l'impression que non.

Voici un exemple extrait de la norme et nettoyé :
class X {
public:
int a;
};

int X::* pmi = &X::a;

void f()
{
X obj;
//...
obj.*pmi = 7; // assign 7 to an integer
}



struct Point
{
int _x, _y;
};

template <typename T>
struct Container
{
typedef std::vector<T> Cltn_t;
Cltn_t _cltn;

template <typename R>
T* Get( const R& value, T::*R member ) /* !!! */


T* Get( const R& value, R T::* member )

{
for ( size_t idx = 0; idx < _cltn.size(); ++idx )
if ( _cltn[idx].*member == value ) /* !!! */
return &_cltn[idx];

return static_cast<T*>( 0 );
}
};



--
Loïc