boost::tuple: iteration mit MPL



  • Ich will folgendes umsetzen:

    Klasse A,B,C erben von Base. Base hat die virtuelle Methode foo().

    Nun will ich ein template bar<tuple_type> haben, welches für A,B,C foo() aufruft:

    menu m;
    create_menu(boost::tuple<A,B,C>(),m);//template funktion, welche das tuple expandiert, und jeweils foo aufruft.
    m.Show();
    

    oder anders gesagt:

    template<class tuple_type, class parameter> void create_menu(tuple_type t,parameter m){for_each<tuple_type>.foo(m);}
    

    Eigentlich müsste das mit boost::tuple und MPL möglich sein. Nur hab ich gerade keinen Plan, wie das umzusetzen ist.

    Also, geht das, und wenn ja wie?

    phlox



  • So ich bin was weiter.

    element<N, T>::type
    und
    length<T>::value

    ergibt zumindest die möglichkeit über alles zu iterieren.

    Ähnlich wie hier:

    template <int N>
    struct Factorial 
    {
        enum { value = N * Factorial<N - 1>::value };
    };
    
    template <>
    struct Factorial<0> 
    {
        enum { value = 1 };
    };
    
    // Factorial<4>::value == 24
    // Factorial<0>::value == 1
    void foo()
    {
        int x = Factorial<4>::value; // == 24
        int y = Factorial<0>::value; // == 1
    }
    

    Nur möchte ich ja auf die Instanzen zugreifen. Was ja mit get<N> geht.

    also ungefähr so:

    template<class tuple_type,int N>
    void do_iterate(tuple_type& t, int i)
    {
    	t.get<i>().foo();
    	do_iterate(t,i-1);
    }
    
    template<class tuple_type,0>
    void do_iterate(tuple_type& t,int i)
    {
    	t.get<0>().foo();
    }
    
    template<class tuple_type>
    void iterate_tuple(tuple_type& t)
    {
    	do_iterate(t,boost::length<tuple_type>::value);
    }
    

    Leider klappt das nicht? 😕
    Mach ich irgendwo einen Fehler?

    phlox



  • So, jetzt hab ich es so hingebogen das es klappt:

    template<class tuple_type,int N>
    struct do_iterate {
      static void call(tuple_type &t) {
        boost::get<N>(t).foo();
        do_iterate<tuple_type, N-1>::call(t);
      }
    };
    
    template<class tuple_type>
    struct do_iterate<tuple_type, 0> {
      static void call(tuple_type &t) {
        boost::get<0>(t).foo();
      }
    };
    
    template<class tuple_type>
    void iterate_tuple(tuple_type &t)
    {
    	do_iterate<tuple_type, boost::tuples::length<tuple_type>::value -1 >::call(t);
    }
    

    phlox



  • Hab gerade gesehen, das das auch recht einfach mit boost::fusion geht:
    http://spirit.sourceforge.net/dl_more/fusion_v2/libs/fusion/doc/html/fusion/quick_start.html



  • thema war genau was ich gesucht hatte, danke dass du die infos auch weitergibst.


Log in to reply