¿Por qué no es posible sobrecargar las plantillas de clase?


Leyendo esta pregunta me hizo preguntarme: ¿hay una razón técnica para no permitir sobrecargas de plantillas de clase?

Por sobrecarga, me refiero a tener varias plantillas con los mismos nombres, pero diferentes parámetros, por ejemplo

template <typename T>
struct Foo {};

template <typename T1, typename T2>
struct Foo {};

template <unsigned int N>
struct Foo {};

El compilador se las arregla para manejar funciones sobrecargadas y plantillas de funciones, ¿no sería posible aplicar las mismas técnicas (por ejemplo, alteración de nombres) a las plantillas de clases?

Al principio, pensé que tal vez eso causaría algunos problemas de ambigüedad al tomar el identificador de plantilla solo, pero la única vez que esto puede suceder es cuando se pasa como un argumento de plantilla de plantilla, por lo que el tipo del parámetro podría usarse para elegir la sobrecarga adecuada:

template <template <typename> class T>
void A {};

template <template <unsigned int> class T>
void B {};

A<Foo> a; // resolves to Foo<T>
B<Foo> b; // resolves to Foo<N>

¿Cree que tal característica podría ser útil? ¿Hay algunas razones" buenas " (es decir, técnicas) por las que esto no es posible en C++actual?

Author: Community, 2012-08-15

3 answers

Sección 12.5 de Plantillas la Guía completa (Amazon ) contiene esta cita:

Usted puede preguntarse legítimamente por qué solo las plantillas de clase pueden ser parcialmente especializadas. Las razones son en su mayoría históricas. Probablemente sea posible definir el mismo mecanismo para las plantillas de funciones (véase el capítulo 13).

De alguna manera el el efecto de sobrecargar las plantillas de funciones es similar, pero también hay algunas diferencias sutiles. Estas diferencias son principalmente relacionado con el hecho de que la plantilla primaria debe ser miró hacia arriba cuando se encuentra un uso. Las especializaciones son considerado solo después, para determinar qué implementación debe ser utilizar.

En contraste, todas las plantillas de funciones sobrecargadas deben ser traídas en un conjunto de sobrecarga mirándolos hacia arriba, y pueden venir de diferentes espacios de nombres o clases. Esto aumenta la probabilidad de sobrecargar involuntariamente un nombre de plantilla de alguna manera.

Inversamente, también es imaginable para permitir una forma de sobrecarga de plantillas de clase. He aquí un ejemplo:

// invalid overloading of class templates
template<typename T1, typename T2> class Pair; 
template<int N1, int N2> class Pair; 

Sin embargo, no parece haber una necesidad apremiante de tal mecanismo.

Además, el Diseño y la Evolución de C++ (Amazon ) contiene esta cita en la sección 15.10.3

Por lo tanto, concluí que necesitábamos un mecanismo para " especializarnos" plantilla. Esto podría hacerse ya sea mediante la aceptación general sobrecargar o por algún mecanismo más específico. Elegí un mecanismo específico porque pensé que estaba abordando principalmente las irregularidades causadas por irregularidades en C y porque las sugerencias de sobrecarga invariablemente crea un aullido de protestas. Estaba tratando de ser cauteloso y conservador; Ahora lo considero un error. Especialización como originalmente definido era una forma restringida y anómala de sobrecarga que encajaba mal con el resto de la idioma.

Negrita énfasis mío. Interpreto esto como diciendo que la resolución de sobrecarga de funciones es más difícil de implementar (y obtener correctamente por los usuarios) que la especialización de clase. Así que probablemente no hay obstáculos técnicos reales (similar para la especialización parcial de la plantilla de función) sino un accidente histórico.

 33
Author: TemplateRex,
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
2018-09-22 09:47:59

No puede "sobrecargar" el parámetro de tipo, el argumento que no es de tipo y el parámetro de plantilla de plantilla, pero puede especializar la plantilla variádica:

template <typename... T>
struct Foo;

template <typename T1>
struct Foo<T1> {};

template <typename T1, typename T2>
struct Foo<T1,T2> {};
 16
Author: log0,
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
2012-08-15 12:21:07

Esto ha existido por un tiempo, pero todavía encontré este post al buscar. Gracias a @log0 por proporcionarme un buen comienzo. Aquí hay una solución que evita la necesidad de proporcionar una especialización de plantilla para todas las enumeraciones posibles. Hace una suposición: que puede definir cada expansión de plantilla en términos de sí misma y sus clases base. (Esto se haría en FooImpl a continuación):

template <typename... T>
struct Foo;

template<typename T>
struct Foo<T> { /* implementation of base class goes here*/};

template <typename C, typename Base>
struct FooImpl : public Base { /* implementation of derived class goes here */};

template<typename C, typename... Bases>
struct Foo<C, Bases...> : FooImpl<C, Foo<Bases...> > { /*NO IMPLEMENTATION HERE */};

El uso de FooImpl rompe la recursión ambigua que de otra manera resulta. Esto entonces permite declaraciones como las siguientes:

Foo<int> foo_int;
Foo<int, double> foo_int_double;
Foo<int, float, double> foo_int_float_double;

Tal vez así es como el STL lo hace ahora?

 0
Author: Chris Bowen,
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
2018-01-13 07:40:13