[Análisis en profundidad de C ++] 44. Análisis en profundidad de la especialización de plantillas de plantillas de clase

1 plantilla de clase multiparamétrica

  • Las plantillas de clase pueden definir cualquier número de parámetros de tipo diferentes

Inserte la descripción de la imagen aquí

Especialización de plantilla tipo 2

Las plantillas de clase pueden ser especializadas

  • Especificar una implementación específica de la plantilla de clase.
  • Algunos parámetros de tipo deben especificarse explícitamente
  • Implemente plantillas de clase por separado basadas en parámetros de tipo
  • El compilador elige automáticamente lo mejor

Inserte la descripción de la imagen aquí

La especialización de plantilla de clase se puede dividir en especialización parcial y especialización completa

  • Especialización parcial-> parámetros de tipo de restricción con reglas específicas
  • Especialización completa-> muestra completamente los parámetros de tipo especificados

Inserte la descripción de la imagen aquí
Experimento de programación: especialización de plantilla de clase

// 44-1.cpp
#include<iostream>
using namespace std;
template<typename T1, typename T2>
class Test
{
public:
    void add(T1 a, T2 b)
    {
        cout << "void add(T1 a, T2 b)" << endl;
        cout << a + b << endl;
    }
};

template<typename T1, typename T2>
class Test<T1*, T2*>				// 关于指针的特化实现
{
public:
    void add(T1* a, T2* b)
    {
        cout << "void add(T1* a, T2* b)" << endl;
        cout << *a + *b << endl;
    }
};

template<typename T>
class Test<T, T>					// 当 Test 类模板的两个类型参数完全相同时,使用这个实现
{
public:
    void add(T a, T b)
    {
        cout << "void add(T a, T b)" << endl;
        cout << a + b << endl;
    }
    void print()
    {
        cout << "class Test<T, T>" << endl;
    }
};

template<>
class Test<void*, void*>			// 当 T1 == void* 并且 T2 == void* 时
{
public:
    void add(void* a, void* b)
    {
        cout << "void add(void* a, void* b)" << endl;
        cout << "Error to add void* param..." << endl;
    }
};
int main()
{
    Test<int, float>t1;			// 必须显示指明每一个类型参数
    Test<long, long>t2;
    Test<void*, void*>t3;

    t1.add(1, 2.5);
    t2.add(5, 5);
    t2.print();

    t3.add(NULL, NULL);

    Test<int*, double*>t4;
    int a = 1;
    double b = 0.1;
    t4.add(&a, &b);
    return 0;
}
  • El código anterior define primero una clase de plantilla y luego ofrece tres especializaciones. La especialización es esencialmente la misma plantilla de clase. El compilador siempre elige la mejor combinación para la implementación.
  • t1.add (1, 2.5); prueba de clase de llamada
  • t2.add (5, 5); clase de llamada Test <T, T>
  • t3.add (NULL, NULL); 调用 Prueba de clase <void *, void *>
  • t4.add (& a, & b); 调用 Prueba de clase <T1 *, T2 *>
$ g++ 44-1.cpp -o 44-1
$ ./44-1
void add(T1 a, T2 b)
3.5
void add(T a, T b)
10
class Test<T, T>
void add(void* a, void* b)
Error to add void* param...
void add(T1* a, T2* b)
1.1

Asuntos que requieren atención:

  • La especialización pertenece esencialmente al mismo tipo de plantilla, pero es una implementación separada de la plantilla
  • El uso de plantillas de clases especiales es uniforme, y cada parámetro de tipo debe especificarse explícitamente

Especialización de plantilla de 3 funciones

Las plantillas de funciones solo admiten la especialización completa de parámetros de tipo
Inserte la descripción de la imagen aquí
Experimentos de programación: especialización de plantillas de funciones

// 44-2.cpp
#include<iostream>
using namespace std;
template<typename T>
bool Equal(T a, T b)
{
    cout << "bool Equal(T a, T b)" << endl;
    return a == b;
}

template<>
bool Equal<double>(double a, double b)
{
    const double delta = 0.00000000000001;
    double r = a - b;
    cout << "bool Equal<double>(double a, double b)" << endl;
    return (-delta < r) && (r < delta);
}

bool Equal(double a, double b)
{
    const double delta = 0.00000000000001;
    double r = a - b;
    cout << "bool Equal(double a, double b)" << endl;
    return (-delta < r) && (r < delta);
}
int main()
{
    cout << Equal(1, 1) << endl;
    cout << Equal<>(0.01, 0.01) << endl;		// 指定使用模板
    cout << Equal(0.1, 0.1) << endl;
    return 0;
}
  • bool Equal (T a, T b) es una plantilla de función. La comparación de dos números de punto flotante no puede usar directamente '==', por lo que para lograr la especialización de plantilla de función bool Equal (doble a, doble b), la plantilla de función solo puede ser completamente especializada. Los dos son esencialmente la misma plantilla, pero se implementan por separado
  • bool Equal (doble a, doble b) es una sobrecarga de funciones.
  • El compilador elige automáticamente lo mejor
  • Igual (1, 1) seleccionará la plantilla bool Igual (T a, T b)
  • Igual <> (0.01, 0.01) 使用 模板 bool Igual <double> (doble a, doble b)
  • Equal (0.1, 0.1) usa la función sobrecargada bool Equal (doble a, doble b),

Compilar y ejecutar

$ g++ 44-2.cpp -o 44-2
$ ./44-2
bool Equal(T a, T b)
1
bool Equal<double>(double a, double b)
1
bool Equal(double a, double b)
1

Recomendación: cuando es necesario sobrecargar plantillas de funciones, se da prioridad al uso de la especialización de plantillas . Cuando la especialización de plantillas no puede cumplir los requisitos, utilice plantillas de funciones.

4 Resumen

1. La plantilla de clase puede definir cualquier número de parámetros de tipo diferentes
2. La plantilla de clase puede estar parcialmente especializada y completamente especializada. La especialización es esencialmente una implementación separada de la plantilla
3. La plantilla de función solo admite la especialización completa

Publicado 298 artículos originales · elogiado 181 · 100,000+ vistas

Supongo que te gusta

Origin blog.csdn.net/happyjacob/article/details/104543091
Recomendado
Clasificación