Domanda

Sono attualmente in fase di scrittura sovraccarichi operatore aritmetico per le tuple. L'operatore itera sulla tupla per eseguire l'operazione su ogni suo singolo elemento. Ecco la definizione per l'operatore + =:

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. Ad 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;

restituisce 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 ...>&)

Il che è strano dato che la condizione std::enable_if dovrebbe rifiutare la chiamata inadeguato. Per ora, ho la seguente soluzione che era in realtà la mia prima realizzazione. La versione di cui 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);
}

Questa compila e funziona come previsto. Perché la versione semplificata rifiuti per compilare? Grazie.

È stato utile?

Soluzione

Utilizzando argomenti template esplicitamente specificato in un modello di funzione o di classe richiede che tutte le confezioni dei parametri del modello appaiono alla fine della lista complessiva parametro di template. Spostamento Ts... alla fine degli elenchi di parametri del modello e la modifica delle chiamate in modo appropriato rende il codice di lavoro. Sezione 14.8.2.1 di la corrente C ++ 0x progetto stati che dei parametri confezioni che non sono alla fine della lista dei parametri del modello non può essere desunta da una chiamata di funzione (che rende il vostro codice originale fallire), ma specificare esplicitamente tutti gli argomenti di template per operator+= in tutti i casi provoca ancora un errore di SFINAE. Una domanda precedente ha un link al testo esatto che proibisce lo ; IBM documentazione dice che è un errore così.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top