numeric_limits c++ templates

numeric_limits - double limits c++



¿Qué significa la plantilla<unsigned int N>? (4)

Es perfectamente posible moldear una clase en un entero en lugar de un tipo. Podemos asignar el valor de plantilla a una variable, o manipularlo de otra manera de cualquier manera con cualquier otro literal entero:

unsigned int x = N;

De hecho, podemos crear algoritmos que se evalúan en tiempo de compilación (de Wikipedia ):

template <int N> struct Factorial { enum { value = N * Factorial<N - 1>::value }; }; template <> struct Factorial<0> { enum { value = 1 }; }; // Factorial<4>::value == 24 // Factorial<0>::value == 1 void foo() { int x = Factorial<4>::value; // == 24 int y = Factorial<0>::value; // == 1 }

Al declarar una plantilla, estoy acostumbrado a tener este tipo de código:

template <class T>

Pero en esta pregunta , usaron:

template <unsigned int N>

Comprobé que compila. Pero, ¿qué significa? ¿Es un parámetro sin tipo? Y si es así, ¿cómo podemos tener una plantilla sin ningún tipo de parámetro?


Sí, es un parámetro sin tipo. Puede tener varios tipos de parámetros de plantilla

  • Tipo de Parámetros.
    • Tipos
    • Plantillas (solo clases y plantillas de alias, sin funciones ni plantillas de variables)
  • Parámetros sin tipo
    • Punteros
    • Referencias
    • Expresiones constantes integrales

Lo que tienes allí es del último tipo. Es una constante de tiempo de compilación (llamada expresión constante) y es de tipo entero o enumeración. Después de buscarlo en el estándar, tuve que mover las plantillas de clases a la sección de tipos, aunque las plantillas no son tipos. Pero se llaman parámetros de tipo con el fin de describir esos tipos, no obstante. Puede tener punteros (y también punteros de miembro) y referencias a objetos / funciones que tienen enlaces externos (aquellos a los que se puede vincular desde otros archivos de objetos y cuya dirección es única en todo el programa). Ejemplos:

Parámetro de tipo de plantilla:

template<typename T> struct Container { T t; }; // pass type "long" as argument. Container<long> test;

Parámetro entero de la plantilla:

template<unsigned int S> struct Vector { unsigned char bytes[S]; }; // pass 3 as argument. Vector<3> test;

Parámetro de puntero de plantilla (pasando un puntero a una función)

template<void (*F)()> struct FunctionWrapper { static void call_it() { F(); } }; // pass address of function do_it as argument. void do_it() { } FunctionWrapper<&do_it> test;

Parámetro de referencia de la plantilla (que pasa un número entero)

template<int &A> struct SillyExample { static void do_it() { A = 10; } }; // pass flag as argument int flag; SillyExample<flag> test;

Parámetro de plantilla de plantilla.

template<template<typename T> class AllocatePolicy> struct Pool { void allocate(size_t n) { int *p = AllocatePolicy<int>::allocate(n); } }; // pass the template "allocator" as argument. template<typename T> struct allocator { static T * allocate(size_t n) { return 0; } }; Pool<allocator> test;

Una plantilla sin ningún parámetro no es posible. Pero una plantilla sin ningún argumento explícito es posible: tiene argumentos predeterminados:

template<unsigned int SIZE = 3> struct Vector { unsigned char buffer[SIZE]; }; Vector<> test;

Sintácticamente, la template<> está reservada para marcar una especialización de plantilla explícita, en lugar de una plantilla sin parámetros:

template<> struct Vector<3> { // alternative definition for SIZE == 3 };


Templalate su clase basado en un ''unsigned int''.

Ejemplo:

template <unsigned int N> class MyArray { public: private: double data[N]; // Use N as the size of the array }; int main() { MyArray<2> a1; MyArray<2> a2; MyArray<4> b1; a1 = a2; // OK The arrays are the same size. a1 = b1; // FAIL because the size of the array is part of the // template and thus the type, a1 and b1 are different types. // Thus this is a COMPILE time failure. }


Una clase de plantilla es como una macro, solo que mucho menos malvada.

Piensa en una plantilla como una macro. Los parámetros de la plantilla se sustituyen en una definición de clase (o función) cuando define una clase (o función) utilizando una plantilla.

La diferencia es que los parámetros tienen "tipos" y los valores pasados ​​se verifican durante la compilación, como los parámetros de las funciones. Los tipos válidos son sus tipos normales de C ++, como int y char. Cuando crea una instancia de una clase de plantilla, pasa un valor del tipo que ha especificado, y en una nueva copia de la definición de la clase de la plantilla, este valor se sustituye en cualquier lugar donde el nombre del parámetro estaba en la definición original. Como una macro.

También puede usar los tipos " class " o " typename " para los parámetros (son realmente los mismos). Con un parámetro de uno de estos tipos, puede pasar un nombre de tipo en lugar de un valor. Al igual que antes, en todas partes donde el nombre del parámetro estaba en la definición de la clase de la plantilla, tan pronto como crea una nueva instancia, se convierte en el tipo que pase. Este es el uso más común para una clase de plantilla; Todo el mundo que sabe algo sobre plantillas C ++ sabe cómo hacerlo.

Considere este código de ejemplo de clase de plantilla:

#include <cstdio> template <int I> class foo { void print() { printf("%i", I); } }; int main() { foo<26> f; f.print(); return 0; }

Funcionalmente es lo mismo que este código de uso macro:

#include <cstdio> #define MAKE_A_FOO(I) class foo_##I / { / void print() / { / printf("%i", I); / } / }; MAKE_A_FOO(26) int main() { foo_26 f; f.print(); return 0; }

Por supuesto, la versión de la plantilla es mil millones de veces más segura y más flexible.