Plantillas - expansión de parámetros Variable de plantilla

Plantillas - expansión de parámetros Variable de plantilla

Una plantilla de parámetro variable

C ++ 11 plantillas mejoradas, C ++ 11 antes, plantillas de clase y plantillas de función sólo contienen un número fijo de parámetros de plantilla, nuevas propiedades son ahora el parámetro variable en C ++ 11 permite que la plantilla a la plantilla incluida en la definición 0 cualquier parámetro de plantilla. plantillas de parámetros variables semánticas y la plantilla Normal es el mismo, sólo en una redacción ligeramente diferente, necesidad de traer de vuelta a la elipsis declaración de nombre de tipo o clase de plantilla parámetro variable "...."

El papel de la elipsis es doble:

  • Declarar un paquete de parámetro, el paquete puede contener 0 parámetro a cualquier parámetro de plantilla.
  • En el paquete de parámetros de la plantilla de los derechos definidos se puede expandir en un un parámetro independiente.

En segundo lugar, la función de plantilla variable del parámetro

1. Definiciones

template <class... T>
void f(T... args){
        cout << sizeof...(args) << endl;        //打印变参的个数
}
f();                                            // 0
f(1, 2);                                        // 2
f(1, 2.5, "");                                  // 3

2, plantilla Parámetros de los modos despliegue de la bolsa

1) el modo de paquete expandido parámetro de función recursiva

Ampliar los parámetros de paquetes mediante una función recursiva, un parámetro necesario para expandir una función del paquete y terminar una función recursiva, una función se usa para terminar la terminación recursiva de la recursividad, los siguientes ejemplos se ven.

#include <iostream>
using namespace std;

// 递归终止函数
void print(){
  cout << "empty" << endl;
}
/*
或者
template <class T>
void print(T t){
  cout << t << endl;
}
或者
template<typename T,typename T1, typename T2>
void print(T t, T1 t1){
        cout<<t<<""<<t1 <<endl;
}
或者
void print(T t, T1 t1, T2 t2){
        cout<<t<<""<<t1<<""<<t2<<endl;
}
*/

// 展开函数
template <class T, class ...Args>
void print(T head, Args... rest){
  cout << "parameter " << head << endl;
  print(rest...);
}
int main(void){
  print(1,2,3,4);
  return 0;
}

Regular la salida de cada parámetro, hasta que la salida es vacío vacío. Hay dos funciones, una es una función recursiva, y el otro es una función recursiva para terminar, paquete parámetro Args ... llama a sí mismo de forma recursiva en el proceso de despliegue, cada uno de los parámetros de llamada de parámetros una vez un paquete serán menos, hasta que todos los parámetros se expanden hasta el momento cuando no hay parámetros, entonces llaman una función fun no molde para terminar el proceso recursivo.

Proceso llamada recursiva es la siguiente:

print(1,2,3,4);
print(2,3,4);
print(3,4);
print(4);
print();
/*
或者
print(1,2,3,4);
print(2,3,4);
print(3,4);
print(4);
*/

También puede :: manera enable_if través std :: tupla y std:

template<std::size_t I = 0, typename Tuple>
typename std::enable_if<I == std::tuple_size<Tuple>::value>::type printtp(Tuplet){
}
template<std::size_t I = 0, typename Tuple>
typename std::enable_if<I < std::tuple_size<Tuple>::value>::type printtp(Tuplet){
        std::cout << std::get<I>(t) << std::endl;
        printtp<I + 1>(t);
}
template<typename... Args>
void print(Args... args){
        printtp(std::make_tuple(args...));
}

En el código anterior, para seleccionar las sobrecargas de plantilla correspondientes parámetros de impresión variables std :: enable_if, la idea básica es que los parámetros variables en la plantilla tupla, la función de impresión se seleccionan entonces incrementando el índice de parámetro cuando el parámetro cuando el índice es menor que el número total de parámetros, los parámetros se toman de forma continua y dando salida a un índice actual, la recursión termina cuando el parámetro de índice es igual al número total de parámetros.

2) Ampliar la expresión paquete de coma parámetro de inicialización y una lista de formas

paquete de parámetro extensión de la función recursiva es una práctica estándar, que se entiende mejor, sino que también tiene un inconveniente, es que debe poner fin a una función recursiva sobrecargado, esa función debe tener una terminación del mismo nombre para terminar la recursividad, se sentirá un poco inconveniente . ¿Hay una manera más simple, ampliar directamente a la bolsa de parámetros? De hecho, puede que no haya una manera de ampliar los parámetros del paquete de forma recursiva, esta necesidad manera de utilizar una coma y expresiones lista de inicialización.

template <class ...Args>
void expand(Args... args){
  std::initializer_list<int>{(printarg(args), 0)...};
}
或者
template<typename... Args>
void expand (Args... args){
        std::initializer_list<int>{([&]{cout << args << endl; }(), 0)...};
}

{(Printarg (args), 0) ...} se extenderá a ((printarg (arg1), 0), (printarg (arg2), 0), (printarg (arg3), 0), etc ...)

En tercer lugar, la clase de plantilla parámetros variables

2, se infla una bolsa parámetros del modo

1) plantillas recursivas y formas especializadas para ampliar el paquete de parámetros

Los parámetros variables requieren generalmente clase plantilla de implementación se define clases 2-3, y que comprende una plantilla especificada clase declaración de la clase. Definen como sigue una clase básica plantilla parámetro variable, este clase es el efecto suma del tamaño de los parámetros calculados en el tipo de parámetro y de paquetes en tiempo de compilación la suma <int, doble, corto> :: valor que pueden ser adquiridos 3 y el tipo de tamaño de 14.

  • Ordinaria de tres etapas
//前向声明
template<typename... Args>
struct Sum;

//定义
template<typename First, typename... Rest>
struct Sum<First, Rest...>{
        enum { value = Sum<First>::value +Sum< Rest...>::value};
};

//特化终止递归
template<typename Last>
struct Sum<Last>{
        enum { value = sizeof (Last) };
};
/*
或者 最后2个参数结束
template<typename First, typename Last>
struct sum<First, Last>{
        enum{ value = sizeof(First) +sizeof(Last) };
};
或者 最后0个参数结束
template<>
struct sum<> { 
	enum{ value = 0 }; 
};
*/
  • También se puede cambiar a una de dos etapas
//定义
template<typename First, typename... Rest>
struct sum{
        enum { value = Sum<First>::value+Sum< Rest...>::value };
};

//特化
template<typename Last>
struct sum<Last>{
        enum{ value = sizeof(Last) };
};

También puede ser eliminado por std :: enumeración integral_constant define el valor, el uso std :: integral_constant puede obtener las características de las constantes de tiempo de compilación, resumir el ejemplo anterior se puede cambiar para esto:

// 前向声明
template<typename... Args>
struct sum;

// 基本定义
template<typename First, typename... Rest>
struct sum<First, Rest...> : std::integral_constant<int, sum<First>::value + sum<Rest...>::value>
{
};
// 递归终止
template<typename Last>
struct sum<Last> : std::integral_constant<int, sizeof(Last)>{
};
sum<int,double,short>::value;// 值为14
Publicados 155 artículos originales · ganado elogios 15 · vistas 160 000 +

Supongo que te gusta

Origin blog.csdn.net/wangdamingll/article/details/105142949
Recomendado
Clasificación