tail von std::tuple
-
Hallo zusammen,
ich habe eine Template-Funktion, die std::tuple gleicher Länge als Parameter erhält. Jetzt möchte ich über beide Tupel gleichzeitig drüberiterieren.
Also schematisch dachte ich an sowas:#include<iostream> #include<tuple> template<typename H1, typename... T1, typename H2, typename... T2> void print(const std::tuple<H1, T1...>& t1, const std::tuple<H2, T2...>& t2){ std::cout << std::get<0>(t1) << " " << std::get<0>(t2) << std::endl; //print(static_cast<const std::tuple<T1...>&>(t1), static_cast<const std::tuple<T2...>&>(t2)); //print(t1.tail(), t2.tail()); //print(t1.get_tail(), t2.get_tail()); } int main(){ typedef std::tuple<int, char, double> tuple_type1; tuple_type1 t1(1, 'c', 1.1); typedef std::tuple<char, double, int> tuple_type2; tuple_type2 t2('b', 2.2, 2); print(t1, t2); }
Also hier einfach paarweise Ausgabe.
Wie ihr allerdings seht, habe ich keine Ahnung wie ich an das Tail des std::tuple drankomme.
Also mit einer eigenen Tupel-Implementierung, wüsste ich, wie man es hinkriegt, aber es sollte doch auch mit einem std::tuple möglich sein.
Kann mir jemand weiterhelfen?Gruß,
XSpilleEDIT: const in static_cast ergänzt
-
Das ist leider nicht möglich, tuple sind keine Listen.
-
Zum Iterieren über Tupel macht sich immer Boost.Fusion gut. Ungetesteter Code:
struct print { template<class T> void operator()(const T& t) const { std::cout << t << " "; } } tuple_type1 t1(1, 'c', 1.1); boost::fusion::for_each(t1, print());
Fusion bietet unter anderem auch Iteratoren und verschiedene andere Datentypen (z.B. auch Listen).
-
otze schrieb:
Das ist leider nicht möglich, tuple sind keine Listen.
Ich danke dir...
Auch wenn ich es kaum glauben kann...@ipsec: Ich möchte allerdings über zwei Tupel gleichzeitig iterieren
-
XSpille schrieb:
@ipsec: Ich möchte allerdings über zwei Tupel gleichzeitig iterieren
Ungenau gelesen. Aber das geht auch mit Fusion (diesmal mit Iteratoren):
template<class It1, class ItEnd1, class It2, class ItEnd2> void print(const It1& begin1, const ItEnd1& end1, const It2& begin2, const ItEnd2& end2) { if(begin1 == end1 || begin2 == end2) return; std::cout << *it1 << ' ' << *it2 << std::endl; // oder boost::fusion::deref(it) print(boost::fusion::next(it1), end1, boost::fusion::next(it2), end2); } tuple_type1 t1(...); tuple_type2 t2(...); print(boost::fusin::begin(t1), boost::fusion::end(t1), boost::fusion::begin(t2), boost::fusion::end(t2));
Oder so ungefähr. Sollten dir die Iteratoren zu umständlich sein, kannst du auch
boost::fusion::pop_front
verwenden, um aus deinem Tupel ein neues ohne erstes Element zu zaubern. Zum Zugriff solltest du aber dannboost::fusion::front
nehmen, da beipop_front
nicht zwingend wieder ein Tupel rauskommt.
-
Ich danke dir ipsec!
EDIT2:Geht einem da nicht die Typsicherheit verloren?
Ich kucks mir später nochmal genauer an, aber jetzt brauch ich noch ne Mütze SchlafWegen der Vollständigkeit, poste ich auch einfach mal, welchen Workaround ich mir ansonsten gebaut hätte:
#include<iostream> #include<tuple> template<bool B, int I, typename T1, typename T2> class Printer{ public: static void print(const T1& t1, const T2& t2){} }; template<int I, typename T1, typename T2> class Printer<true, I, T1, T2>{ public: static const int SIZE = std::tuple_size<T1>::value; static const bool GO = I<SIZE-1; static void print(const T1& t1, const T2& t2){ std::cout << std::get<I>(t1) << " " << std::get<I>(t2) << std::endl; Printer<GO, I+1, T1, T2>::print(t1, t2); } }; template<typename... T1, typename... T2> void print(const std::tuple<T1...>& t1, const std::tuple<T2...>& t2){ Printer<true, 0, std::tuple<T1...>, std::tuple<T2...> >::print(t1, t2); } int main(){ typedef std::tuple<int, char, double> tuple_type1; tuple_type1 t1(1, 'c', 1.1); typedef std::tuple<char, double, int> tuple_type2; tuple_type2 t2('b', 2.2, 2); print(t1, t2); }
Gruß,
XSpilleEDIT: Geht natürlich so nicht für zwei leere Tupel
EDIT3: Modifizierte Variante:
#include<iostream> #include<tuple> template<int I, int Max> class Printer{ public: template<typename T1, typename T2> static void print(const T1& t1, const T2& t2){ std::cout << std::get<I>(t1) << " " << std::get<I>(t2) << std::endl; Printer<I+1, Max>::print(t1, t2); } }; template<int I> class Printer<I, I>{ public: template<typename T1, typename T2> static void print(const T1& t1, const T2& t2){} }; template<typename... T1, typename... T2> void print(const std::tuple<T1...>& t1, const std::tuple<T2...>& t2){ Printer<0, std::tuple_size<std::tuple<T1...> >::value>::print(t1, t2); } int main(){ typedef std::tuple<int, char, double> tuple_type1; tuple_type1 t1(1, 'c', 1.1); typedef std::tuple<char, double, int> tuple_type2; tuple_type2 t2('b', 2.2, 2); print(t1, t2); }
-
Iteriere doch einfach über die Indizes.
Ansatz:
template<int N, int C> struct ctfor_helper { template<class Functor> static void doit(Functor& f) { f(std::integral_constant<int,C>()); ctfor_helper<N-1,C+1>::doit(f); } }; template<int C> struct ctfor_helper<0,C> { template<class Functor> static void doit(Functor&) {} } template<int B, int E, class Functor> Functor compile_time_for(Functor fun) { ctfor_helper<E-B,B>::doit(fun); return fun; } ... int main() { auto x = make_tuple(42, 3.1415, 'c'); auto y = make_tuple(99, 2.7182, 'x'); compile_time_for<0,3>(blah(x,y)); }
Was `blah` ist, kannst Du Dir selbt überlegen.
-
Danke krümelkacker!
Die Idee hatte ich von Anfang an als 'Not-Lösung', aber ich hoffte, dass es einen schöneren Weg gibt
-
XSpille schrieb:
Danke krümelkacker!
Die Idee hatte ich von Anfang an als 'Not-Lösung', aber ich hoffte, dass es einen schöneren Weg gibt
So hässlich finde ich das gar nicht. Der erste Teil ist halbwegs generisch/wiederverwendbar.
Das Tuple-spezifische beschränkt sich auf
template<class T1, class T2> struct blah { T1& t1; T2& t2; blah(T1& t1, T2& t2) : t1(t1), t2(t2) {} template<int I> void operator()(std::integral_constant<int,I>) { cout << std::get<I>(t1) << ", " << std::get<I>(t2) << '\n'; } };
Mit polymorphen Lambdas wäre das wahrscheinlich noch schöner geworden:
auto tuple1 = make_tuple(23,3.14159265,'p'); auto tuple2 = make_tuple(99,2.71828183',x'); compile_time_for<0,3>([&](auto index_tag){ constexpr int idx = decltype(index_tag)::value; cout << std::get<idx>(tuple1) << ", " << std::get<idx>(tuple2) << '\n'; });
Aber so etwas wie "polymorphe Lambdas" (siehe auto als Lambda-Parameter-Typ) gibt es leider nicht.
Das mit den Fusion-Iteratoren sieht auch nett aus. Allerdings macht es mir etwas Sorgen, dass die Abbruchbedingung als "Laufzeit-If-Return" dort steht.
-
krümelkacker schrieb:
Das mit den Fusion-Iteratoren sieht auch nett aus. Allerdings macht es mir etwas Sorgen, dass die Abbruchbedingung als "Laufzeit-If-Return" dort steht.
Muss sie nicht. Man kann zur Compilezeit mit
boost::fusion::result_of::equal_to<It, ItEnd>::type
arbeiten (z.B. inenable_if
). Nach ein bisschen Nachforschen stieß ich aber auch auf denzip_view
. Der macht aus mehreren Sequenzen eine Sequenz von Tupeln der Originalelemente:struct print { template<class Tupel> void operator()(const Tuple& t) { std::cout << at_c<0>(t) << ' ' << at_c<1>(t) << std::endl; } } for_each(zip(t1, t2), print());
Dank der Mächtigkeit von Fusion und mit einer Lambda-Bibliothek (welche mit Boost.ResultOf zusammen spielen muss) geht es sogar mit einem Einzeiler:
for_each(zip(t1, t2), make_fused(std::cout << _1 << ' ' << _2 << std::endl));
-
ipsec schrieb:
Muss sie nicht.
Echt nicht?
Also bei folgendem Code
#include<iostream> #include <boost/fusion/sequence.hpp> #include <boost/fusion/include/sequence.hpp> #include <boost/fusion/adapted/boost_tuple.hpp> #include <boost/fusion/iterator.hpp> template<class It1, class ItEnd1, class It2, class ItEnd2> void print(const It1& begin1, const ItEnd1& end1, const It2& begin2, const ItEnd2& end2) { if(begin1 == end1 || begin2 == end2) return; std::cout << boost::fusion::deref(begin1) << ' ' << boost::fusion::deref(begin2) << std::endl; print(boost::fusion::next(begin1), end1, boost::fusion::next(begin2), end2); } int main(){ typedef boost::tuple<int, char, double> tuple_type1; tuple_type1 t1(1, 'c', 1.1); typedef boost::tuple<char, double, int> tuple_type2; tuple_type2 t2('b', 2.2, 2); print(boost::fusion::begin(t1),boost::fusion::end(t1),boost::fusion::begin(t2),boost::fusion::end(t2)); }
erhalte ich eine ellenlange Fehlermeldung, die unter anderem folgende Zeilen enthält:
test6.cpp:13:5: error: no matching function for call to 'deref(const boost::fusion::boost_tuple_iteratorboost::tuples::null_type&)'
test6.cpp:14:5: error: no matching function for call to 'next(const boost::fusion::boost_tuple_iteratorboost::tuples::null_type&)'
Für mich (als Hobby-Programmierer) sieht es allerdings so aus als würde die Bedingung nicht greifen...
-
Hm sieht so aus, als muss man es zur Compilezeit prüfen (z.B. mit
enable_if
). Bei genauerer Betrachtung eigentlich auch logisch [Hintergrund: die Position des Iterators verändert dessen Typ, d.h.decltype(it) != decltype(next(it))
. Offenbar prüftderef
schon zur Compiletime, statt zur Runtime, ob der Iterator gültig ist]. Leider ist es mir z.Z. nicht möglich, die Codes zu testen. Funktioniert denn das andere mit demzip
?
-
Dann frag ich mal vorsichtig:
Welche Bedingungen werden zur Compilierzeit denn schon ausgewertet?Ich dachte wirkliche Meta-Programmierung geht nur über typedefs und Konstanten...
In folgendem einfachen Beispiel scheint die Bedingung schon nicht zu greifen:
template<int I> void endless(){ endless<I+1>(); } template<int I> void print(){ if(I==1) endless<0>(); } int main(){ print<0>(); }
test7.cpp: In function 'void endless() [with int I = 1022]':
test7.cpp:4:2: error: template instantiation depth exceeds maximum of 1024 (use -ftemplate-depth= to increase the maximum) instantiating 'void endless() [with int I = 1023]'
test7.cpp:4:2: recursively instantiated from 'void endless() [with int I = 1]'
test7.cpp:4:2: instantiated from 'void endless() [with int I = 0]'
test7.cpp:10:3: instantiated from 'void print() [with int I = 0]'
test7.cpp:16:11: instantiated from here
-
ipsec schrieb:
Funktioniert denn das andere mit dem
zip
?Also folgender Code
#include <iostream> #include <boost/fusion/sequence/intrinsic/at_c.hpp> #include <boost/fusion/adapted/boost_tuple.hpp> #include <boost/fusion/algorithm/transformation/zip.hpp> #include <boost/foreach.hpp> #define foreach BOOST_FOREACH struct print { template<class Tuple> void operator()(const Tuple& t) { std::cout << boost::fusion::at_c<0>(t) << ' ' << boost::fusion::at_c<1>(t) << std::endl; } }; int main(){ typedef boost::tuple<int, char, double> tuple_type1; tuple_type1 t1(1, 'c', 1.1); typedef boost::tuple<char, double, int> tuple_type2; tuple_type2 t2('b', 2.2, 2); foreach(boost::fusion::zip(t1, t2), print()); }
führt zu dieser Fehlermeldung, die ich persönlich nicht zuordnen kann:
In file included from /opt/local/include/boost/mpl/aux_/begin_end_impl.hpp:20:0,
from /opt/local/include/boost/mpl/begin_end.hpp:18,
from /opt/local/include/boost/mpl/is_sequence.hpp:19,
from /opt/local/include/boost/fusion/support/detail/is_mpl_sequence.hpp:12,
from /opt/local/include/boost/fusion/support/tag_of.hpp:13,
from /opt/local/include/boost/fusion/sequence/intrinsic/at.hpp:12,
from /opt/local/include/boost/fusion/sequence/intrinsic/at_c.hpp:10,
from test8.cpp:2:
/opt/local/include/boost/mpl/eval_if.hpp: In instantiation of 'boost::mpl::eval_if<mpl_::bool_<true>, boost::range_const_iterator<print>, boost::range_mutable_iterator<print> >':
/opt/local/include/boost/foreach.hpp:355:13: instantiated from 'boost::foreach_detail_::foreach_iterator<print, mpl_::bool_<true> >'
test8.cpp:22:2: instantiated from here
/opt/local/include/boost/mpl/eval_if.hpp:38:31: error: no type named 'type' in 'boost::mpl::eval_if<mpl_::bool_<true>, boost::range_const_iterator<print>, boost::range_mutable_iterator<print> >::f_'
test8.cpp: In function 'int main()':
test8.cpp:22:2: error: no matching function for call to 'begin(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<print, mpl_::bool_<true> >, boost::mpl::or_<boost::mpl::and_<boost::mpl::not_<boost::is_array<print> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, boost::mpl::and_<boost::mpl::not_<boost::foreach::is_noncopyable<print> >, boost::foreach::is_lightweight_proxy<print>, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, mpl_::bool_<false>, mpl_::bool_<false>, mpl_::bool_<false> >)'
test8.cpp:22:2: note: candidates are:
/opt/local/include/boost/foreach.hpp:637:61: note: template<class T, class C> boost::foreach_detail_::auto_any<typename boost::foreach_detail_::foreach_iterator<T, C>::type> boost::foreach_detail_::begin(boost::foreach_detail_::auto_any_t, boost::foreach_detail_::type2type<T, C>, mpl_::true_)
/opt/local/include/boost/foreach.hpp:645:62: note: template<class T, class C> boost::foreach_detail_::auto_any<typename boost::foreach_detail_::foreach_iterator<T, C>::type> boost::foreach_detail_::begin(boost::foreach_detail_::auto_any_t, boost::foreach_detail_::type2type<T, C>, mpl_::false_)
/opt/local/include/boost/foreach.hpp:666:63: note: template<class T, class C> boost::foreach_detail_::auto_any<T*> boost::foreach_detail_::begin(boost::foreach_detail_::auto_any_t, boost::foreach_detail_::type2type<T*, C>, mpl_::true_)
test8.cpp:22:2: error: no matching function for call to 'end(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<print, mpl_::bool_<true> >, boost::mpl::or_<boost::mpl::and_<boost::mpl::not_<boost::is_array<print> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, boost::mpl::and_<boost::mpl::not_<boost::foreach::is_noncopyable<print> >, boost::foreach::is_lightweight_proxy<print>, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, mpl_::bool_<false>, mpl_::bool_<false>, mpl_::bool_<false> >)'
test8.cpp:22:2: note: candidates are:
/opt/local/include/boost/foreach.hpp:677:59: note: template<class T, class C> boost::foreach_detail_::auto_any<typename boost::foreach_detail_::foreach_iterator<T, C>::type> boost::foreach_detail_::end(boost::foreach_detail_::auto_any_t, boost::foreach_detail_::type2type<T, C>, mpl_::true_)
/opt/local/include/boost/foreach.hpp:685:60: note: template<class T, class C> boost::foreach_detail_::auto_any<typename boost::foreach_detail_::foreach_iterator<T, C>::type> boost::foreach_detail_::end(boost::foreach_detail_::auto_any_t, boost::foreach_detail_::type2type<T, C>, mpl_::false_)
/opt/local/include/boost/foreach.hpp:706:57: note: template<class T, class C> boost::foreach_detail_::auto_any<int> boost::foreach_detail_::end(boost::foreach_detail_::auto_any_t, boost::foreach_detail_::type2type<T*, C>, mpl_::true_)
test8.cpp:22:2: error: no matching function for call to 'deref(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<print, mpl_::bool_<true> >)'
test8.cpp:22:2: note: candidate is:
/opt/local/include/boost/foreach.hpp:745:40: note: template<class T, class C> typename boost::foreach_detail_::foreach_reference::type boost::foreach_detail_::deref(boost::foreach_detail_::auto_any_t, boost::foreach_detail_::type2type<T, C>)
-
Edit: zum Fehler mit
zip
: möglicherweise hilft es schon, den operator() const zu machen. Compilerfehlermeldungen sind ein Graus.Offenbar geht es in deinem Beispiel nicht mal mit Spezialisierung, da immer versucht wird,
endless<0>
zu generieren (auch wenn es nie gebraucht wird).
Bei den Iteratoren ist der Fall aber anders. Folgende Funktion sollte z.B. schon funktionieren (der Einfachhalt halber mit nur einem Iterator)template<class It, class ItEnd> void foo(It it, ItEnd end) { do_something(deref(it)); foo(next(it), end); } template<class ItEnd> void foo(ItEnd, ItEnd) { }
Wobei
equal_to
aber vermutlich der korektere Weg wäre. Mit 2 Iteratoren ist es natürlich etwas aufwendiger. Du könntest annehmen, dass die zweite Sequenz immer mindestens so lang ist, wie die erste, dann brauchst du nur einen end-Iterator (Verstöße werden zur Compilezeit erkannt). Oder du sparst dir die Iteratoren ganz und nimmst sowas wiepop_back
oderzip
.
-
ipsec schrieb:
Edit: zum Fehler mit
zip
: möglicherweise hilft es schon, den operator() const zu machen. Compilerfehlermeldungen sind ein Graus.Nein... Ein
void operator() const (const Tuple& t)
verändert (scheinbar) gar nichts (ohne jetzt alles 100%ig verglichen zu haben)
-
Ok zum zip-Fehler: das foreach ist nicht etwas BOOST_FOREACH, sondern boost::fusion::for_each. Folgender Code funktioniert (seit etwa 1min weiß ich, dass ideone Boost installiert hat, also konnte ich testen):
#include <iostream> #include <boost/fusion/sequence/intrinsic/at_c.hpp> #include <boost/fusion/adapted/boost_tuple.hpp> #include <boost/fusion/algorithm/transformation/zip.hpp> #include <boost/fusion/include/for_each.hpp> struct print { template<class Tuple> void operator()(const Tuple& t) const { std::cout << boost::fusion::at_c<0>(t) << ' ' << boost::fusion::at_c<1>(t) << std::endl; } }; int main(){ typedef boost::tuple<int, char, double> tuple_type1; tuple_type1 t1(1, 'c', 1.1); typedef boost::tuple<char, double, int> tuple_type2; tuple_type2 t2('b', 2.2, 2); boost::fusion::for_each(boost::fusion::zip(t1, t2), print()); }
Ausgabe
1 b c 2.2 1.1 2
-
ipsec schrieb:
Folgende Funktion sollte z.B. schon funktionieren (der Einfachhalt halber mit nur einem Iterator)
Komplettes (nicht-)kompilierfähiges Programm:
#include <iostream> #include <boost/fusion/sequence.hpp> #include <boost/fusion/include/sequence.hpp> #include <boost/fusion/adapted/boost_tuple.hpp> #include <boost/fusion/iterator.hpp> template<class It, class ItEnd> void foo(It it, ItEnd end) { do_something(deref(it)); foo(next(it), end); } template<class ItEnd> void foo(ItEnd, ItEnd) { } int main(){ typedef boost::tuple<int, char, double> tuple_type1; tuple_type1 t1(1, 'c', 1.1); typedef boost::tuple<char, double, int> tuple_type2; tuple_type2 t2('b', 2.2, 2); foo(boost::fusion::begin(t1),boost::fusion::end(t1)); }
Diesmal mit kompletter Fehlermeldung, auch wenn es für mich nach dem gleichen Problem aussieht:
test9.cpp: In function 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::tuple<int, char, double> >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null_type]':
test9.cpp:25:53: instantiated from here
test9.cpp:11:5: error: 'do_something' was not declared in this scope
test9.cpp: In function 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::cons<char, boost::tuples::cons<double, boost::tuples::null_type> > >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type]':
test9.cpp:12:5: instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::tuple<int, char, double> >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null_type]'
test9.cpp:25:53: instantiated from here
test9.cpp:11:5: error: 'do_something' was not declared in this scope
test9.cpp: In function 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::cons<double, boost::tuples::null_type> >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type]':
test9.cpp:12:5: recursively instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::cons<char, boost::tuples::cons<double, boost::tuples::null_type> > >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type]'
test9.cpp:12:5: instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::tuple<int, char, double> >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null_type]'
test9.cpp:25:53: instantiated from here
test9.cpp:11:5: error: 'do_something' was not declared in this scope
In file included from /opt/local/include/boost/fusion/sequence/comparison/detail/equal_to.hpp:12:0,
from /opt/local/include/boost/fusion/sequence/comparison/equal_to.hpp:14,
from /opt/local/include/boost/fusion/sequence/comparison.hpp:10,
from /opt/local/include/boost/fusion/sequence.hpp:11,
from test9.cpp:2:
/opt/local/include/boost/fusion/iterator/deref.hpp: At global scope:
/opt/local/include/boost/fusion/iterator/deref.hpp: In instantiation of 'boost::fusion::extension::deref_implboost::fusion::iterator\_facade\_tag::apply<boost::fusion::boost_tuple_iteratorboost::tuples::null\_type >':
/opt/local/include/boost/fusion/iterator/deref.hpp:50:16: instantiated from 'boost::fusion::result_of::deref<boost::fusion::boost_tuple_iteratorboost::tuples::null\_type >'
test9.cpp:12:5: recursively instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::cons<char, boost::tuples::cons<double, boost::tuples::null_type> > >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type]'
test9.cpp:12:5: instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::tuple<int, char, double> >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null_type]'
test9.cpp:25:53: instantiated from here
/opt/local/include/boost/fusion/iterator/deref.hpp:34:20: error: no class template named 'deref' in 'struct boost::fusion::boost_tuple_iteratorboost::tuples::null_type'
test9.cpp: In function 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type]':
test9.cpp:12:5: recursively instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::cons<char, boost::tuples::cons<double, boost::tuples::null_type> > >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type]'
test9.cpp:12:5: instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::tuple<int, char, double> >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null_type]'
test9.cpp:25:53: instantiated from here
test9.cpp:11:5: error: no matching function for call to 'deref(boost::fusion::boost_tuple_iteratorboost::tuples::null_type&)'
test9.cpp:11:5: note: candidate is:
/opt/local/include/boost/fusion/iterator/deref.hpp:58:5: note: template<class Iterator> typename boost::fusion::result_of::deref::type boost::fusion::deref(const Iterator&)
test9.cpp:11:5: error: 'do_something' was not declared in this scope
In file included from /opt/local/include/boost/fusion/sequence/comparison/detail/equal_to.hpp:13:0,
from /opt/local/include/boost/fusion/sequence/comparison/equal_to.hpp:14,
from /opt/local/include/boost/fusion/sequence/comparison.hpp:10,
from /opt/local/include/boost/fusion/sequence.hpp:11,
from test9.cpp:2:
/opt/local/include/boost/fusion/iterator/next.hpp: At global scope:
/opt/local/include/boost/fusion/iterator/next.hpp: In instantiation of 'boost::fusion::extension::next_implboost::fusion::iterator\_facade\_tag::apply<boost::fusion::boost_tuple_iteratorboost::tuples::null\_type >':
test9.cpp:12:5: recursively instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::cons<char, boost::tuples::cons<double, boost::tuples::null_type> > >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type]'
test9.cpp:12:5: instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::tuple<int, char, double> >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null_type]'
test9.cpp:25:53: instantiated from here
/opt/local/include/boost/fusion/iterator/next.hpp:33:20: error: no class template named 'next' in 'struct boost::fusion::boost_tuple_iteratorboost::tuples::null_type'
test9.cpp: In function 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type]':
test9.cpp:12:5: recursively instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::cons<char, boost::tuples::cons<double, boost::tuples::null_type> > >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null\_type]'
test9.cpp:12:5: instantiated from 'void foo(It, ItEnd) [with It = boost::fusion::boost_tuple_iterator<boost::tuples::tuple<int, char, double> >, ItEnd = boost::fusion::boost_tuple_iteratorboost::tuples::null_type]'
test9.cpp:25:53: instantiated from here
test9.cpp:12:5: error: no matching function for call to 'next(boost::fusion::boost_tuple_iteratorboost::tuples::null_type&)'
test9.cpp:12:5: note: candidate is:
/opt/local/include/boost/fusion/iterator/next.hpp:57:5: note: template<class Iterator> const typename boost::fusion::result_of::next::type boost::fusion::next(const Iterator&)
-
ipsec schrieb:
Ok zum zip-Fehler: das foreach ist nicht etwas BOOST_FOREACH, sondern boost::fusion::for_each. Folgender Code funktioniert (seit etwa 1min weiß ich, dass ideone Boost installiert hat, also konnte ich testen)
Okay...
So funktioniert es jedenfalls auch bei mirEDIT: und was kann BOOST_FOREACH, was boost::fusion::for_each nicht kann bzw. umgekehrt?
-
fusion::for_each ist fuer fusion container. also heterogene datentypen wie tuple. BOOST_FOREACH ist fuer homogene Container (also std::vector<double>).