C++ Academy · Lección

Patrones con enable_if

Restrinja plantillas de la forma clásica

Lección 4 de 413 pasos

Patrones con enable_if es una lección gratuita de C++ Academy en CoddyKit. Esta es la lección 4 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 enable_if?

std::enable_if es un pequeño rasgo que define condicionalmente un miembro type. Cuando la condición es verdadera, el tipo existe; cuando es falsa, la plantilla envolvente se elimina mediante SFINAE.

  • Se encuentra en <type_traits>.
  • Es la herramienta clásica para restringir plantillas.
#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
doubleIt(T v) { return v * 2; }

int main() {
    std::cout << doubleIt(21) << '\n';
    return 0;
}

Cómo funciona

enable_if<Cond, T>::type es T solo cuando Cond es verdadera. Si es falsa, no existe ningún miembro type, por lo que falla la sustitución.

#include <iostream>
#include <type_traits>

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

enable_if en el tipo de retorno

La ubicación más habitual es el tipo de retorno. La función solo existe cuando se cumple la condición.

#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
half(T v) { return v / 2; }

int main() {
    std::cout << half(5.0) << '\n';
    return 0;
}

enable_if como parámetro de plantilla

Otro recurso coloca enable_if en un parámetro de plantilla predeterminado, manteniendo limpio el tipo de retorno.

#include <iostream>
#include <type_traits>

template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
T triple(T v) { return v * 3; }

int main() {
    std::cout << triple(4) << '\n';
    return 0;
}

El atajo enable_if_t

C++14 añadió el alias std::enable_if_t<Cond, T> para poder omitir el código redundante de typename ...::type.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, T>
negate(T v) { return -v; }

int main() {
    std::cout << negate(8) << '\n';
    return 0;
}

Emparejamiento de dos sobrecargas

Proporcione condiciones complementarias de modo que exactamente una sobrecarga sea válida para cualquier tipo, sin ambigüedades.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, const char*>
category() { return "integer"; }

template <typename T>
std::enable_if_t<!std::is_integral<T>::value, const char*>
category() { return "non-integer"; }

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

Combinación de condiciones

Utilice operadores lógicos sobre los valores de los rasgos para expresar restricciones más completas, como «integral y con signo».

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, T>
magnitude(T v) { return v < 0 ? -v : v; }

int main() {
    std::cout << magnitude(-12) << '\n';
    return 0;
}

Restricción de un constructor

Puede colocar enable_if en el parámetro de plantilla de un constructor para permitirlo solo con tipos compatibles.

#include <iostream>
#include <type_traits>

struct Wrapper {
    int value;
    template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
    Wrapper(T v) : value(static_cast<int>(v)) {}
};

int main() {
    Wrapper w(42);
    std::cout << w.value << '\n';
    return 0;
}

Problema con el argumento de plantilla predeterminado

Dos sobrecargas que solo difieren en un parámetro de plantilla enable_if predeterminado se consideran redefiniciones. Déles formas diferentes; por ejemplo, coloque una condición en el tipo de retorno.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
printKind() { std::cout << "int\n"; }

template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
printKind() { std::cout << "float\n"; }

int main() {
    printKind<int>();
    printKind<double>();
    return 0;
}

Comparación con los conceptos

Los conceptos de C++20 sustituyen la mayoría de los usos de enable_if con una sintaxis mucho más clara, pero enable_if sigue siendo esencial para el código anterior a C++20 y para algunos casos límite.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_arithmetic<T>::value, T>
square(T v) { return v * v; }

int main() {
    std::cout << square(6) << ' ' << square(1.5) << '\n';
    return 0;
}

Un ejemplo completo

Combine todos los elementos: una familia de funciones que formatea los enteros y los números de coma flotante de forma diferente, seleccionada en tiempo de compilación.

#include <iostream>
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, void>
format(T v) { std::cout << "int[" << v << "]\n"; }

template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void>
format(T v) { std::cout << "float(" << v << ")\n"; }

int main() {
    format(10);
    format(3.5);
    return 0;
}

Comprobación rápida

Compruebe su comprensión de enable_if.

Resumen

Ha aprendido los patrones clásicos de enable_if:

  • define ::type solo cuando la condición es verdadera, lo que habilita SFINAE
  • se coloca en el tipo de retorno o en un parámetro de plantilla predeterminado
  • utilice el alias enable_if_t y combine rasgos con operadores lógicos
  • los conceptos lo sustituyen en C++20, pero sigue utilizándose ampliamente

Con esto termina el curso de especialización de plantillas y SFINAE.

Gratis para empezar

Aprende C++ con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
51
Lecciones
203

Preguntas frecuentes

¿La lección «Patrones con enable_if» es gratis?

Sí — el texto completo de «Patrones con enable_if» 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 «Patrones con enable_if»?

Restrinja plantillas de la forma clásica 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 4 de 4.

¿Cuánto tiempo toma la lección «Patrones con enable_if»?

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