web-dev-qa-db-fra.com

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

Je sais que la spécification du langage interdit partielle la spécialisation du modèle de fonction.

Je voudrais savoir pourquoi il 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!
74
Nawaz

AFAIK qui a changé en C++ 0x.

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

Vous pouvez rechercher le DR (rapport de défaut) pertinent, s'il y en a un.

[~ # ~] modifier [~ # ~] : en vérifiant cela, je trouve que d'autres ont également cru cela, mais personne n'est capable de trouver un tel soutien dans le projet de norme. Ce SO semble indiquer que la spécialisation partielle des modèles de fonction n'est pas prise en charge en C++ 0x.

EDIT 2 : juste un exemple de ce que je voulais dire par "placer la fonction comme 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
}
52
Cheers and hth. - Alf

En général, il n'est pas recommandé de spécialiser les modèles de fonction du tout, en raison de problèmes de surcharge. Voici un bon article du Journal des utilisateurs C/C++: 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 simplement parce que la langue dit que vous ne pouvez pas.

13
Georgy Pashkov

Eh bien, vous ne pouvez vraiment pas faire de spécialisation partielle de fonction/méthode, mais vous pouvez faire une 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 ça vous satisfait.

12
Michal W

Comme 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 ;
}
9
Kay F. Jahnke