2017-08-07 2 views
4

J'ai une fonction de modèle qui fait quelque chose avec une valeur donnée tant que le type de modèle est un numéro:surcharge de fonction de modèle (type générique vs type de modèle de modèle) choisir de surcharge correcte

template <typename scalar_t> 
void function(scalar_t value) 
{ 
    if constexpr (std::is_floating_point_v<scalar_t>) 
    { 
     std::cout << value << 'F'; 
    } 
    if constexpr (std::is_integral_v<scalar_t>) 
    { 
     std::cout << value; 
    } 
} 

Et une surcharge pour ce modèle attend un conteneur contenant des nombres:

template <typename scalar_t, template <typename> class container_t> 
void function(const container_t<scalar_t> &container) 
{ 
    for (const auto &value : container) 
    { 
     function(value); 
     std::cout << ' '; 
    } 
} 

Avec les modèles ci-dessus, j'appelle le code suivant:

int main() 
{ 
    function('0'); 
    function(short{1}); 
    function(2); 
    function(3l); 
    function(4ll); 
    function(5.f); 
    function(6.); 

    std::vector<int> v{7, 8, 9, 10}; 
    std::list<double> l{11., 12., 13., 14.}; 

    function(v); 
    function(l); 

    return 0; 
} 

Ce qui donne le résultat suivant:

F6F 

Pendant que je me attendais à la sortie suivante:

F6F7 8 9 10 11F 12F 13F 14F 

Ce qui signifie que la première version du modèle (function(scalar_t value)) a été choisi au lieu de la deuxième version (function(const container_t<scalar_t> &container)).

Comment puis-je forcer la sélection de la deuxième version de la fonction de modèle pour les paramètres de modèle de modèle?

+0

ne sais pas si c'est le problème, mais les deux '' vECTOR' et list' n'avez pas un, mais deux paramètres du modèle – user463035818

+0

@ tobi303 [ C'était le problème en effet] (https://wandbox.org/permlink/kvKHSpDJ6VEOWhRO) si vous pouvez expliquer pourquoi dans une réponse, je peux l'incriminer :) –

Répondre

2

Le problème ici est que vos types de modèles ne correspondent pas. std::vector et std::list ont tous deux un paramètre de modèle pour l'allocateur. template <typename> class container_t ne permet pas que le modèle ne correspond pas, donc void function(scalar_t value) est appelé et rien ne se passe.

Ce que vous devez faire est de prendre un paramètre de modèle de modèle variadique. En utilisant

template <typename scalar_t, template <typename...> class container_t> 
void function(const container_t<scalar_t> &container) 
{ 
    for (const auto &value : container) 
    { 
     function(value); 
     std::cout << ' '; 
    } 
} 

Vous obtenez

F6F7 8 9 10 11F 12F 13F 14F 

Live Example

+0

Fait intéressant, 'gcc' et' clang' fonctionnent différemment avec ce code. Est-ce que 'clang' est correct? –

+0

@EdgarRokyan C'est intéressant. AFAIK, clang se comporte correctement ici. Je ne sais pas pourquoi gcc l'accepte. – NathanOliver

+1

@EdgarRokyan On dirait que quelque chose a changé dans gcc entre C++ 14 et 17. [this] (http://coliru.stacked-crooked.com/a/e814e634d60dfeaf) ne parvient pas à compiler en mode C++ 14 mais compile en C++ 17 mode. Maintenant, je ne suis pas sûr si quelque chose est arrivé en C++ 17 pour l'autoriser ou si c'est un bug dans l'implémentation C++ 17 de gcc. – NathanOliver