2017-08-14 1 views
5

Existe-t-il un moyen de coder une fonction de modèle unique pouvant s'exécuter sur différents membres d'un struct?Fonction de modèle sur les membres de structure

Un mauvais exemple ressemblerait à ceci:

struct Foo 
{ 
    int a, b; 
} 

template <MEMBER x> //which does not exist 
cout_member(Foo foo) 
{ 
    cout << foo.x << endl; 
} 

int main() 
{ 
    Foo foo; 
    cout_member<a>(foo); 
    cout_member<b>(foo); 
    return 0; 
} 

J'ai imaginé une réponse basée sur un interrupteur, mais je puis me demandais si ce commutateur sera testé sur l'exécution (ce que je voudrais éviter) ou à la compilation?

+1

Pourquoi avez-vous besoin de cela? – user0042

+0

Je suis en train de résoudre un système d'équations dérivées dérivées partielles pour une grille 2D, et j'aimerais avoir une fonction dérivée unique pour toutes les quantités physiques de chaque cellule ... Ou au moins réduire le nombre de fonctions à copier coller ! –

+0

Semble superflu et encombrant peut-être un problème XY. –

Répondre

10

Tant que vous voulez prendre un membre de données à partir d'un ensemble d'éléments de données ayant le même type, vous pouvez utiliser un pointeur vers un membre de données:

template <int Foo::*M> 
void cout_member(Foo foo) 
{ 
    std::cout << (foo.*M) << std::endl; 
} 

et l'utiliser comme:

cout_member<&Foo::a>(foo); 

Si vous voulez indiquer également le type, vous pouvez le faire:

template <typename T, T Foo::*M> 
void cout_member(Foo foo) 
{ 
    std::cout << (foo.*M) << std::endl; 
} 

et l'utiliser comme:

cout_member<int, &Foo::a>(foo); 

Juste par curiosité, le second extrait serait encore plus simple dans C de 17:

template <auto M> 
void cout_member(Foo foo) 
{ 
    std::cout << (foo.*M) << std::endl; 
} 

Voir vers le haut et en cours d'exécution sur wandbox;

+0

Merci! Je vais prendre la version C++ 17! –

+0

Bien sûr! Je suis désolé d'avoir essayé il y a quelques heures mais il m'a fallu beaucoup de temps pour comprendre comment le faire ... Est-ce que ça va maintenant? –

+0

@ valadeaurélien Yep. Et bienvenue sur SO. – skypjack

1

Vous pouvez tirer parti std::mem_fn de sorte que vous n'avez même pas se soucier: (non testé)

template < typename Fun, typename ... Params > 
void print(Fun f, Params && ... p) { std::cout << f(std::forward<Params>(p)...) << "\n"; } 

print(std::mem_fn(&Obj::fun), Obj()); 

Puisque vous utilisez les flux que vous ne se soucient probablement pas ... mais cela ne devrait ajouter peu à zéro frais généraux de simplement écrire cout << obj.fun().

Editer: mem_fn Fonctionne aussi pour les membres de données. Crée un callable qui renvoie une référence à la valeur que vous pouvez ensuite utiliser: int x = mem_fn(&pair<int,char>::first)(my_pair);

+0

@skypjack - http://fr.cppreference.com/w/cpp/utility/functional/mem_fn –

+0

Assez juste. J'ai mal compris la réponse. Je vous remercie. – skypjack