0Pricing
C++ Academy · Lección

Especialización parcial

Especialice patrones de plantillas

Especialización parcial es una lección gratuita de C++ Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C++ Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C++ Academy incluye 4 lecciones en total.

¿Qué es la especialización parcial?

La especialización parcial personaliza una plantilla para una familia de tipos que comparten un patrón, en lugar de para un único tipo exacto.

  • Solo las plantillas de clase la admiten.
  • Aún se dejan algunos parámetros genéricos.
#include <iostream>

template <typename T>
struct Traits { static const char* kind() { return "value"; } };

template <typename T>
struct Traits<T*> { static const char* kind() { return "pointer"; } };

int main() {
    std::cout << Traits<int>::kind() << '\n';
    std::cout << Traits<int*>::kind() << '\n';
    return 0;
}

Coincidencia con punteros

El patrón T* coincide con cualquier tipo de puntero, lo que permite gestionar todos los punteros con una sola especialización.

#include <iostream>

template <typename T>
struct Deref { static T get(T v) { return v; } };

template <typename T>
struct Deref<T*> { static T get(T* p) { return *p; } };

int main() {
    int x = 42;
    std::cout << Deref<int>::get(7) << '\n';
    std::cout << Deref<int*>::get(&x) << '\n';
    return 0;
}

Las funciones no admiten especialización parcial

Solo las plantillas de clase (y de variable) admiten especialización parcial. Para las funciones, se utiliza la sobrecarga.

#include <iostream>

template <typename T>
void show(T) { std::cout << "value\n"; }

template <typename T>
void show(T*) { std::cout << "pointer\n"; }

int main() {
    int x = 0;
    show(5);
    show(&x);
    return 0;
}

Especialización de uno de dos parámetros

Con varios parámetros de tipo, puede fijar uno y dejar abierto el otro para que coincida con un patrón entre distintos tipos.

#include <iostream>

template <typename A, typename B>
struct Pair { static const char* kind() { return "mixed"; } };

template <typename A>
struct Pair<A, A> { static const char* kind() { return "same types"; } };

int main() {
    std::cout << Pair<int, double>::kind() << '\n';
    std::cout << Pair<int, int>::kind() << '\n';
    return 0;
}

Coincidencia con matrices

Puede hacer coincidir tipos de matriz mediante un patrón que capture el tipo de elemento y el tamaño como parámetro que no es de tipo.

#include <iostream>

template <typename T>
struct Info { static int size() { return 1; } };

template <typename T, int N>
struct Info<T[N]> { static int size() { return N; } };

int main() {
    std::cout << Info<int>::size() << '\n';
    std::cout << Info<int[5]>::size() << '\n';
    return 0;
}

Patrones const

Una especialización puede eliminar o detectar const haciendo coincidir const T como patrón.

#include <iostream>

template <typename T>
struct IsConst { static const bool value = false; };

template <typename T>
struct IsConst<const T> { static const bool value = true; };

int main() {
    std::cout << std::boolalpha;
    std::cout << IsConst<int>::value << '\n';
    std::cout << IsConst<const int>::value << '\n';
    return 0;
}

Se elige la más especializada

Cuando pueden coincidir varias especializaciones, el compilador elige la más especializada, es decir, el patrón más específico.

#include <iostream>

template <typename T>
struct K { static int v() { return 0; } };

template <typename T>
struct K<T*> { static int v() { return 1; } };

template <>
struct K<int*> { static int v() { return 2; } };

int main() {
    std::cout << K<double*>::v() << ' ' << K<int*>::v() << '\n';
    return 0;
}

Patrones de referencia

También puede hacer coincidir tipos de referencia para distinguir una referencia de un valor simple.

#include <iostream>

template <typename T>
struct Cat { static const char* k() { return "value"; } };

template <typename T>
struct Cat<T&> { static const char* k() { return "lvalue ref"; } };

int main() {
    std::cout << Cat<int>::k() << '\n';
    std::cout << Cat<int&>::k() << '\n';
    return 0;
}

Construcción de rasgos de tipos

La especialización parcial es el motor que impulsa los rasgos de tipos. Este es un remove_pointer implementado manualmente.

#include <iostream>
#include <type_traits>

template <typename T>
struct RemovePtr { using type = T; };

template <typename T>
struct RemovePtr<T*> { using type = T; };

int main() {
    std::cout << std::boolalpha;
    std::cout << std::is_same<RemovePtr<int*>::type, int>::value << '\n';
    return 0;
}

Combinación de patrones

Puede combinar patrones; por ejemplo, hacer coincidir un puntero a const para gestionar estructuras de tipos por capas.

#include <iostream>

template <typename T>
struct Desc { static const char* k() { return "plain"; } };

template <typename T>
struct Desc<const T*> { static const char* k() { return "ptr to const"; } };

int main() {
    std::cout << Desc<int>::k() << '\n';
    std::cout << Desc<const int*>::k() << '\n';
    return 0;
}

Un rasgo práctico para contenedores

Utilice una especialización parcial para extraer el tipo de elemento de una plantilla similar a un contenedor.

#include <iostream>
#include <type_traits>

template <typename C>
struct Element { using type = void; };

template <template <typename> class C, typename T>
struct Element<C<T>> { using type = T; };

template <typename T>
struct Box { T item; };

int main() {
    std::cout << std::boolalpha;
    std::cout << std::is_same<Element<Box<int>>::type, int>::value << '\n';
    return 0;
}

Comprobación rápida

Compruebe su comprensión de la especialización parcial.

Resumen

Ha aprendido sobre la especialización parcial:

  • personaliza una plantilla de clase para un patrón de tipos como T* o const T
  • las funciones utilizan sobrecarga, no especialización parcial
  • se elige la versión coincidente más especializada
  • es la base de rasgos de tipos como remove_pointer

A continuación, aprenderá SFINAE, una forma de habilitar funciones solo cuando un tipo cumple los requisitos.

Preguntas frecuentes

¿La lección «Especialización parcial» es gratis?

Sí — el texto completo de «Especialización parcial» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C++ Academy, actualiza a CoddyKit PRO. El curso de C++ Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Especialización parcial»?

Especialice patrones de plantillas Practicas C++ Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C++ Academy?

No se requiere experiencia previa. C++ Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «Especialización parcial»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C++ Academy?

Sí. Cada lección de C++ Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Especialización completa
  2. Especialización parcial
  3. SFINAE
  4. Patrones con enable_if
← Volver a C++ Academy