2013-08-09 4 views
6

Gibt es eine bessere Lösung als manuell ein Dienstprogramm so zu schreiben?Wie man durch std :: tuple iteriert?

template <size_t> struct SizeT { }; 

template < typename TupleType, typename ActionType > 
inline void TupleForEach(TupleType& tuple, ActionType action) 
{ 
    TupleForEach(tuple, action, SizeT<std::tuple_size<TupleType>::value>()); 
} 

template < typename TupleType, typename ActionType > 
inline void TupleForEach(TupleType& tuple, ActionType action, SizeT<0>) { } 

template < typename TupleType, typename ActionType, size_t N > 
inline void TupleForEach(TupleType& tuple, ActionType action, SizeT<N>) 
{ 
    TupleForEach(tuple, action, SizeT<N-1>()); 
    action(std::get<N-1>(tuple)); 
} 

Um wie folgt verwendet werden:

std::tuple<char, int, double> tt; 
TupleForEach(tt, (boost::lambda::_1 = 5)); 
+1

Was sind Ihre Kriterien für "besser"? – Casey

+0

@Casey - Eine Bibliotheksimplementierung in 'std' oder' boost'; wenn nicht, dann eine Implementierung mit weniger Code als das; oder vielleicht gibt es ein Problem bei dieser Implementierung. – Vahagn

Antwort

1

Auch wenn es mehr Antworten in einem previous, related question vorgesehen (und die, die Sie selbst zur Verfügung stellen), mein erster Eindruck ist, dass die Notwendigkeit, über die iteriert Tupel kann ein Spiegelbild eines schlechten Designs sein.

Wie Sie wissen, ist der Grund, warum wir nicht über std::tuple mithilfe von Standard-C++ - Algorithmen iterieren können, weil std::tuple die Container concept nicht erfüllt. Und genau, erfüllt es dieses Konzept nicht, weil std::tuple s keine value_type haben (sie sind heterogen). Ich weiß, dass Sie ein Tupel verwendet haben, weil Sie nicht Ihren eigenen polymorphen Typ erstellen und in einem Standardcontainer speichern möchten (z. B. std::vector<std::shared_ptr<BaseClass>>). Das gab dir einen schnellen Gewinn. Das bedeutet aber auch, dass Sie freiwillig auf die Vorteile von Container s verzichtet haben.

Es mag funktionieren, aber es fühlt sich irgendwie gezwungen und unnatürlich an: Wenn Sie Containersemantik brauchen, warum nicht einen Container verwenden? Wenn Sie eine polymorphe Semantik benötigen, warum nicht einen polymorphen Typ?

Wahrscheinlich übertreibe ich, aber das ist mein erster Eindruck.

+0

Der Grund, warum ich nicht eine polymorphe Basisklasse für Typen im Tupel erstellt habe, ist keine Laune :) Diese Typen sind von Art von Drittanbietern, also wer sie verwendet, ist sicher nicht unbedingt derjenige, der behauptet Sie. Diese Typen haben jedoch ein gemeinsames Konzept, daher sind einige Operationen für jede von ihnen gültig, so dass derjenige, der eine Menge von Objekten dieser Typen speichert, solche Operationen über diese Objekte ausführen möchte. – Vahagn

+4

Betrachte außerdem ein Tupel von 'char',' int' und 'double'. Oder ein Tupel von einigen Zeigern. Im ersten Fall gibt es z.B. eine gültige Operation zum Setzen der Tupelelemente auf Null, und im zweiten Fall gibt es z.B. eine gültige Operation zum Setzen der Tupel-Mitglieder auf "nullptr", aber in C++ ist es sicher eine Art Unsinn, eine Basisklasse für alle arithmetischen Typen oder eine Basisklasse für alle Zeigertypen zu betrachten. – Vahagn