¿Por qué la plantilla de función no puede ser parcialmente especializada?


Sé que la especificación del lenguaje prohíbe la especialización parcial de la plantilla de función.

Me gustaría saber la razón por la que lo prohíbe? ¿No son útiles?

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!
Author: Lightness Races in Orbit, 2011-02-24

4 answers

AFAIK que ha cambiado en C++0x.

Supongo que fue solo un descuido (teniendo en cuenta que siempre se puede obtener el efecto de especialización parcial con un código más detallado, colocando la función como un static miembro de una clase).

Puede buscar el DR (Informe de defectos) relevante, si hay uno.

EDITAR : comprobando esto, encuentro que otros también lo han creído, pero nadie es capaz de encontrar tal apoyo en el borrador del estándar. Esto ES ASÍ thread parece indicar que la especialización parcial de las plantillas de funciones no es compatible con C++0x.

EDIT 2 : solo un ejemplo de lo que quise decir con "colocar la función como un static miembro de una clase":

#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
}
 49
Author: Cheers and hth. - Alf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:17:30

En general, no se recomienda especializar plantillas de función en absoluto, debido a problemas con la sobrecarga. Aquí hay un buen artículo del Diario de Usuarios de C / C++: http://www.gotw.ca/publications/mill17.htm

Y contiene una respuesta honesta a tu pregunta:

Por un lado, no puedes especializarlos parcialmente pretty más o menos porque el idioma dice que no puedes.

 14
Author: Georgy Pashkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-24 07:33:17

Bueno, realmente no se puede hacer la especialización de función/método parcial sin embargo se puede hacer la sobrecarga.

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){...} 

Es el camino, pero no sé si te satisface.

 11
Author: Michal W,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-27 10:06:33

Dado que puede especializar parcialmente las clases, puede usar un funtor:

#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 ;
}
 8
Author: Kay F. Jahnke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-22 17:03:49