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.
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? –
@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