2011-01-28 7 views
9

Attualmente sono in procinto di scrivere sovraccarichi operatore aritmetici per tuple. L'operatore esegue iterazioni sulla tupla per eseguire l'operazione su ciascuno dei suoi singoli elementi. Ecco la definizione per l'operatore + =:C++ - Iterazione su una tupla e risoluzione del tipo rispetto ai parametri costanti

template< typename... Ts, std::size_t I = 0 > 
inline typename std::enable_if< I == sizeof... (Ts), std::tuple<Ts...>& >::type operator +=(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    return lhs; 
} 

template< typename... Ts, std::size_t I = 0 > 
inline typename std::enable_if< I != sizeof... (Ts), std::tuple<Ts...>& >::type operator +=(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    std::get<I>(lhs) += std::get<I>(rhs); 
    return operator +=< Ts..., I + 1 >(lhs, rhs); 
} 

Purtroppo, quando tento di chiamare l'operatore, GCC 4.6 non può decidere quale sovraccaricare dovrebbe usare. Per esempio:

std::tuple< int, int, int, int > a = std::make_tuple(1, 2, 3, 4), b = std::make_tuple(5, 6, 7, 8); 
a += b; 

produce il seguente errore:

:/Workspace/raster/main.cpp:833:7: instantiated from here 
C:/Workspace/raster/main.cpp:809:45: error: no matching function for call to 'operator+=(std::tuple<int, int, int, int>&, const std::tuple<int, int, int, int>&)' 
C:/Workspace/raster/main.cpp:809:45: note: candidates are: 
C:/Workspace/raster/main.cpp:800:151: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I == sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&) 
C:/Workspace/raster/main.cpp:806:83: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I != sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&) 

che è strano in quanto la condizione std::enable_if dovrebbe rifiutare la chiamata inadeguato. Per ora, ho la seguente soluzione alternativa che era in realtà la mia precedente implementazione. La versione sopra è in realtà un tentativo di semplificazione.

template< std::size_t I, typename... Ts > 
inline typename std::enable_if< I == sizeof... (Ts), std::tuple<Ts...>& >::type assignadd_impl(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    return lhs; 
} 

template< std::size_t I, typename... Ts > 
inline typename std::enable_if< I != sizeof... (Ts), std::tuple<Ts...>& >::type assignadd_impl(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    std::get<I>(lhs) += std::get<I>(rhs); 
    return assignadd_impl< I + 1, Ts... >(lhs, rhs); 
} 

template< typename... Ts > 
inline std::tuple<Ts...>& operator +=(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    return assignadd_impl< 0, Ts... >(lhs, rhs); 
} 

Questo compila e funziona come previsto. Perché la versione semplificata rifiuta di compilare? Grazie.

+0

Cosa succede se si sposta il parametro del modello 'I' in primo piano nel primo esempio di codice, come nel secondo che funziona? Questo cambia qualcosa? –

+0

@Jeremiah Willcock - Purtroppo no. Ho provato molte varianti, tra cui la commutazione dell'ordine dei parametri del modello, ma tutte producono lo stesso errore. – pmjobin

risposta

4

L'utilizzo di argomenti del modello specificati esplicitamente su una funzione o un modello di classe richiede che tutti i pacchetti di parametri del modello compaiano alla fine dell'elenco generale dei parametri del modello. Spostare Ts... alla fine degli elenchi dei parametri del modello e modificare le chiamate in modo appropriato rende il codice funzionante. La sezione 14.8.2.1 di the current C++0x draft indica che i pacchetti di parametri che non si trovano alla fine dell'elenco di parametri del modello non possono essere dedotti da una chiamata di funzione (che non consente il codice originale), ma specificando esplicitamente tutti gli argomenti del modello su operator+= in tutti i casi causa ancora un errore SFINAE. A previous question ha un collegamento al testo esatto che lo impedisce; IBM's documentation dice che si tratta di un errore.

+0

Funziona davvero. Non so cosa sia andato storto durante i miei test originali perché a un certo punto avevo invertito gli argomenti del template. Ma grazie comunque. :) – pmjobin

Problemi correlati