Especialización en plantillas de miembros y su alcance.
-
03-07-2019 - |
Pregunta
Me parece que C ++ no permite la especialización de la plantilla de miembros en ningún ámbito que no sea el espacio de nombres y el ámbito global (MS VSC ++ Error C3412). Pero para mí tiene sentido especializar la plantilla de miembro principal de una clase base en la clase derivada porque eso es lo que hacen las clases derivadas: especializar las cosas en la clase base. Por ejemplo, considere el siguiente ejemplo:
struct Base
{
template <class T>
struct Kind
{
typedef T type;
};
};
struct Derived : public Base
{
/* Not Allowed */
using Base::Kind;
template <>
struct Kind <float>
{
typedef double type;
};
};
int main(void)
{
Base::Kind<float>::type f; // float type desired
Derived::Kind<float>::type i; // double type desired but does not work.
}
Mi pregunta es ¿por qué no está permitido?
Solución
Entiendo lo que intentas hacer, pero no lo estás haciendo bien. Prueba esto:
struct Base{};
struct Derived{};
// Original definition of Kind
// Will yield an error if Kind is not used properly
template<typename WhatToDo, typename T>
struct Kind
{
};
// definition of Kind for Base selector
template<typename T>
struct Kind<Base, T>
{
typedef T type;
};
// Here is the inheritance you wanted
template<typename T>
struct Kind<Derived, T> : Kind<Base, T>
{
};
// ... and the specialization for float
template<>
struct Kind<Derived, float>
{
typedef double type;
};
Otros consejos
Mi pregunta es ¿por qué no está permitido?
Desde mi copia del borrador, parece que lo siguiente pone la restricción anterior:
En una declaración de especialización explícita para una plantilla de clase, un miembro de una plantilla de clase o un miembro de clase plantilla, el nombre de la clase que está explícitamente especializada será simple-template-id.
La solución es especializar la clase adjunta.
Voy a " ignorar " Las especificaciones estándar y probar un argumento lógico:
Si tienes dos clases:
class A
{
struct S { };
};
class B: public A
{
struct S { };
};
A :: S y B :: S son dos tipos diferentes. Extendiendo la lógica a las especializaciones de la plantilla, cuando intenta especializar una clase interna declarada en la clase base a través de una clase interna en la clase derivada, en realidad está tratando de definir un tipo diferente, con el mismo nombre (pero con otro ámbito de denominación).