81 votes

Pourquoi le modèle de fonction ne peut pas être partiellement spécialisé ?

Je sais que les spécifications du langage interdisent partiel spécialisation de la fonction modèle.

J'aimerais connaître la raison pour laquelle elle l'interdit ? Ne sont-ils pas utiles ?

template<typename T, typename U> void f() {}   //allowed!
template<> void f<int, char>()            {}   //allowed!
template<typename T> void f<char, T>()    {}   //not allowed!
template<typename T> void f<T, int>()     {}   //not allowed!

56voto

Cheers and hth. - Alf Points 59647

AFAIK, cela a changé dans C++0x.

Je suppose que ce n'était qu'un oubli (étant donné que l'on peut toujours obtenir l'effet de spécialisation partielle avec un code plus verbeux, en plaçant la fonction en tant que static membre d'une classe).

Vous pouvez consulter le DR (Defect Report) correspondant, s'il y en a un.

EDIT : en vérifiant cela, je constate que d'autres personnes l'ont également cru, mais personne n'est en mesure de trouver un tel soutien dans le projet de norme. Ce fil de SO semble indiquer que la spécialisation partielle des modèles de fonctions n'est pas supportée en C++0x .

EDIT 2 : juste un exemple de ce que j'entendais par "placer la fonction en tant que static membre d'une classe" :

#include <iostream>
using namespace std;

// template<typename T, typename U> void f() {}   //allowed!
// template<> void f<int, char>()            {}   //allowed!
// template<typename T> void f<char, T>()    {}   //not allowed!
// template<typename T> void f<T, int>()     {}   //not allowed!

void say( char const s[] ) { std::cout << s << std::endl; }

namespace detail {
    template< class T, class U >
    struct F {
        static void impl() { say( "1. primary template" ); }
    };

    template<>
    struct F<int, char> {
        static void impl() { say( "2. <int, char> explicit specialization" ); }
    };

    template< class T >
    struct F< char, T > {
        static void impl() { say( "3. <char, T> partial specialization" ); }
    };

    template< class T >
    struct F< T, int > {
        static void impl() { say( "4. <T, int> partial specialization" ); }
    };
}  // namespace detail

template< class T, class U >
void f() { detail::F<T, U>::impl(); }    

int main() {
    f<char const*, double>();       // 1
    f<int, char>();                 // 2
    f<char, double>();              // 3
    f<double, int>();               // 4
}

19voto

Michal W Points 773

Eh bien, vous ne pouvez pas vraiment faire de spécialisation partielle de fonction/méthode, mais vous pouvez faire de la surcharge.

template <typename T, typename U>
T fun(U pObj){...}

// acts like partial specialization <T, int> AFAIK 
// (based on Modern C++ Design by Alexandrescu)
template <typename T>
T fun(int pObj){...} 

C'est le chemin mais je ne sais pas si cela vous satisfait.

13voto

Goxa Points 103

En général, il n'est pas du tout recommandé de spécialiser les modèles de fonctions, en raison des problèmes de surcharge. Voici un bon article du C/C++ Users Journal : http://www.gotw.ca/publications/mill17.htm

Et il contient une réponse honnête à votre question :

D'une part, vous ne pouvez pas les spécialiser partiellement - à peu près parce que la langue le dit.

11voto

Kay F. Jahnke Points 371

Puisque vous pouvez spécialiser partiellement les classes, vous pouvez utiliser un foncteur :

#include <iostream>

template < typename dtype , int k > struct fun
{
 int operator()()
 {
  return k ;
 }
} ;

template < typename dtype > struct fun < dtype , 0 >
{
 int operator()()
 {
  return 42 ;
 }
} ;

int main ( int argc , char * argv[] )
{
 std::cout << fun<float,5>()() << std::endl ;
 std::cout << fun<float,0>()() << std::endl ;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X