2013-05-03 8 views
7

Utknął w ziemi TR1, dla programu testowego muszę wykonać pewne operacje na wielu obiektach określonego typu. Mam kilka definicji typu krotek, które wyglądają tak:Jak iterować nad krotką TR1

typedef std::tr1::tuple< bool 
         , signed char 
         , signed short 
         , signed int 
         , signed long long 
         , unsigned char 
         , unsigned short 
         , unsigned int 
         , unsigned long long > integral_types; 

Z każdego typu krotki należy utworzyć obiekt. Następnie mam szablony funkcjonalne podobne do tego:

template<typename T> 
void invoke_operation_1(T& obj); 

Te muszą być wywoływane dla wszystkich obiektów w obiekcie krotki.

Jak to zrobić w C++ 03?

+1

[Co próbowałeś do tej pory?] (Http://mattgemmell.com/2008/12/08/what-have-you-tried/) –

+0

Czy nie 'tuple_size' i 'get' w tr1? – jrok

+0

Metoda [Boost.Fusion] (http://stackoverflow.com/a/1201902/560648) powinna być zgodna z C++ 03. A [podejście manualne] (http://stackoverflow.com/a/1198432/560648) jest tutaj. –

Odpowiedz

3

Możesz użyć boost::fusion, jeśli chcesz wywołać tę samą szablonową funkcję dla każdego obiektu w krotce. Na przykład.

template<typename T> 
void invoke_operation_1(T& obj) 
{ 
    std::cout << obj << std::endl; 
} 

struct executor 
{ 
    template<typename T> 
    void operator()(T& t) const 
    { 
     invoke_operation_1(t); 
    } 
}; 

typedef boost::tuple< bool 
         , signed char 
         , signed short 
         , signed int 
         , signed long long 
         , unsigned char 
         , unsigned short 
         , unsigned int 
         , unsigned long long > integral_types; 
int main() 
{ 
    integral_types t(true, 0, 1, 2, 3, 4, 5, 6, 7); 
    boost::fusion::for_each(t, executor()); 
    return 0; 
} 
+0

Byłem niezdecydowany, aby wprowadzić boost :: fusion, aby to zrobić, ale to wygląda naprawdę wygodnie, więc mógłbym dać i tak spróbować. Jakie warunki musi spełnić 'executor'? Czy zamiast tego będzie działać wyrażenie 'std :: tr1 :: bind()'? Z argumentami zastępczymi? – sbi

+0

@sbi Dokument mówi "Regular Callable Object", więc wyrażenie bind powinno być w porządku. – mkaes

+0

@sbi ponieważ 'invoke_operation_1' jest szablonem, a nie funkcją, wątpię, aby' boost :: bind' działał. Przynajmniej nie mogłem znaleźć żadnych przeciążeń z szablonowymi argumentami, które byłyby potrzebne tutaj. –

8

W Bristol została właśnie sfinalizowana funkcja C++ 14, która rozwiązała ten problem. Nie jest to trudne.

Dla prostszego przypadku można użyć szablonu rekursywnego. To smaganie bałaganu, ale bez specjalizacji częściowej funkcji i takie.

template<typename Tup, std::size_t N> struct visit_detail { 
    template<typename F> static void call(Tup& t, F f) { 
     f(std::tr1::get<N>(t)); 
     return visit_detail<Tup, N+1>::call(t, f); 
    } 
}; 
template<typename Tup> struct visit_detail<Tup, std::tr1::tuple_size<Tup>::value> { 
    template<typename F> static void call(Tup& t, F f) {} 
} 

template<typename Tup, typename F> void visit(Tup& t, F f) { 
    return visit_detail<Tup, 0>::call(t, f); 
} 

Tutaj f może być oznaczony na sztywno lub obiekt funkcji parametru lub cokolwiek chcesz.

+0

Ah, więc rzeczywiście istnieje "tuple_size". Dzięki, myślę, że mogę to rozpracować! – sbi

+0

@DeadMG: Yikes! Czy pamiętasz nazwę funkcji C++ 14, w celach informacyjnych? –

+0

[N3493] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3493.html) nieznacznie zmieniony – Puppy

0
template<typename tup, typename N> 
struct visit_detailImpl { 
    template<typename f> 
    static void call(tup& t, f f) { 
     f(std::tr1::get<N::value>(t)); 
     return visit_detailImpl<tup, std::integral_constant<std::size_t, N::value + 1> >::call(t, f); 
    } 
}; 
template<typename tup> // end recursion struct 
struct visit_detailImpl<tup, std::integral_constant<std::size_t, std::tr1::tuple_size<tup>::value> > { 
    template<typename f> 
    static void call(tup& t, f f) {} 
}; 
template<typename tup, typename Fn> 
void for_each_tup(tup& t, Fn f) { 
    return visit_detailImpl<tup, std::integral_constant<std::size_t, 0> >::call(t, f); 
} 
+0

"Utknięcie w lądowisku TR1 ..." – sbi

Powiązane problemy