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ß,
    XSpille

    EDIT: 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 dann boost::fusion::front nehmen, da bei pop_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 Schlaf 🙂

    Wegen 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ß,
    XSpille

    EDIT: 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. in enable_if ). Nach ein bisschen Nachforschen stieß ich aber auch auf den zip_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üft deref 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 dem zip ?



  • 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 wie pop_back oder zip .



  • 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 mir 👍

    EDIT: 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>).


Log in to reply