2013-05-03 18 views
7

Essendo bloccato in terra TR1, per un programma di test è necessario eseguire determinate operazioni su un numero di oggetti di tipi specifici. Ho un paio di definizioni del tipo tupla che assomigliano a questo:Come eseguire iterazione su una tetra 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; 

Da ogni tipo tupla un oggetto deve essere creato. Allora ho modelli di funzione simile a questo:

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

Questi devono essere chiamati per tutti gli oggetti in un oggetto di tupla.

Come si fa in C++ 03?

+1

[Cosa hai provato finora?] (Http://mattgemmell.com/2008/12/08/what-have-you-tried/) –

+0

Non C'è 'tuple_size' e 'get' in tr1? – jrok

+0

L'approccio [Boost.Fusion] (http://stackoverflow.com/a/1201902/560648) dovrebbe essere compatibile con C++ 03. Un [approccio manuale] (http://stackoverflow.com/a/1198432/560648) è qui. –

risposta

3

È possibile utilizzare boost::fusion se è necessario chiamare la stessa funzione di modello per ogni oggetto nella tupla. Per esempio.

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

Ero esitante a introdurre boost :: fusion solo per farlo, ma questo sembra davvero conveniente, quindi potrei dare è comunque una prova. Quali condizioni deve soddisfare l'esecutore? Funzionerebbe invece un'espressione 'std :: tr1 :: bind()'? Con argomento segnaposto? – sbi

+0

@sbi La docuentazione dice un "oggetto callable regolare", quindi un'espressione di binding dovrebbe essere ok. – mkaes

+0

@sbi poiché 'invoke_operation_1' è un modello e non una funzione, dubito che' boost :: bind' funzionerà. Almeno non sono riuscito a trovare sovraccarichi che richiedessero argomenti modello template, che sarebbero necessari qui. –

8

C'era una funzionalità appena conclusa a Bristol per C++ 14 per risolvere questo problema. Non è troppo difficile da affrontare.

Per il caso più semplice, è possibile utilizzare un modello ricorsivo. È un po 'di confusione senza specializzazione di funzione parziale e così via.

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); 
} 

Qui f può essere hardcoded o un oggetto funzione parametro o qualsiasi altra cosa si desideri.

+0

Ah, quindi c'è davvero un 'tuple_size'. Grazie, penso di poter lavorare da lì! – sbi

+0

@DeadMG: Yikes! Riesci a ricordare il nome della funzione C++ 14, come riferimento? –

+0

[N3493] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3493.html) leggermente rivisto – 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

"Essere bloccato in terra TR1 ..." – sbi