Question

Je suis en train d'écrire l'opérateur arithmétique surcharge pour tuples. L'opérateur parcourt le tuple pour effectuer l'opération sur chacune de ses éléments individuels. Voici la définition de l'opérateur + =:

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

Malheureusement, lorsque je tente d'appeler l'opérateur, GCC 4.6 ne peut pas décider de surcharge, il doit utiliser. Par exemple:

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

Rendements l'erreur suivante:

:/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 ...>&)

Ce qui est étrange puisque la condition de std::enable_if devrait rejeter l'appel inappropriée. Pour l'instant, je la solution suivante qui était en fait ma mise en œuvre préalable. La version ci-dessus est en fait une tentative de simplification.

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

Cette compile et fonctionne comme prévu. Pourquoi la version simplifiée refuse de dresser des? Merci.

Était-ce utile?

La solution

En utilisant des arguments de modèle explicitement spécifié à un modèle de fonction ou de la classe exige que tous les paquets de paramètres du modèle apparaissent à la fin de la liste globale des paramètres du modèle. Déplacement Ts... à la fin des listes de paramètres du modèle et la modification des appels fait correctement le travail de code. Section 14.8.2.1 de le courant C ++ 0x projets de états de ce paquets de paramètres qui ne sont pas à la fin de la liste des paramètres du modèle ne peuvent pas être déduites à partir d'un appel de fonction (ce qui rend votre code original échec), mais spécifiant explicitement tous les arguments de modèle à operator+= dans tous les cas provoque toujours une erreur SFINAE. précédente question a un lien vers le texte exact interdisant ; documentation d'IBM dit qu'il est une erreur aussi bien.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top