2017-08-14 66 views
5

Czy istnieje sposób kodowania pojedynczej funkcji szablonu, która może działać na różnych elementach danego struct?Funkcja szablonu na elementach struktury

źle Przykładem może wyglądać następująco:

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; 
} 

Wyobrażałem sobie odpowiedź oparta na przełączniku, ale potem się zastanawiać, czy ten przełącznik zostanie przetestowany na okresie czasu (co chciałbym uniknąć) lub podczas kompilacji?

+1

Dlaczego tego potrzebujesz? – user0042

+0

Rozwiązuję układ sprzężonych równań pochodnych dla siatki 2D i chciałbym mieć funkcję pochodnej pojedynczej przestrzeni dla wszystkich wielkości fizycznych każdej komórki ... Lub przynajmniej zmniejszyć liczbę funkcji do kopiuj wklej ! –

+0

Wydaje się zbędny i kłopotliwy prawdopodobnie problem XY. –

Odpowiedz

10

Tak długo, jak chcesz, aby podnieść element danych ze zbioru elementów danych o tym samym typie, można użyć wskaźnik do członka danych:

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

i używać go jako:

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

Jeśli chcesz wskazać również rodzaj, można to zrobić:

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

i używać go jako:

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

Tak z ciekawości, drugi fragment będzie jeszcze prostsza w C++ 17:

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

Zobacz uruchomiony na wandbox;

+0

Dzięki! Wezmę wersję C++ 17! –

+0

Oczywiście! Przykro mi, że próbowałem kilka godzin temu, ale zajęło mi dużo czasu, aby zrozumieć, jak to zrobić ... Czy teraz jest ok? –

+0

@ valadeaurélien Tak. Witaj na SO. – skypjack

1

Można wykorzystać std::mem_fn więc nawet nie musisz się martwić: (niesprawdzone)

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()); 

Ponieważ używasz strumienie prawdopodobnie nie obchodzi ... ale to powinno dodać trochę do zera narzut od pisania cout << obj.fun().

Edytuj: mem_fn działa również na elementach danych. Tworzy wywołanie, które zwraca odwołanie do wartości, którą można następnie użyć: int x = mem_fn(&pair<int,char>::first)(my_pair);

+0

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

+0

Wystarczająco fair. Źle zrozumiałem odpowiedź. Dziękuję Ci. – skypjack