course: Programación III
unit: 1
cmake project: prog3_unit2_templates_v2022_1
Subir a gradescope los siguientes archivos:
P1.h
yP1.cpp
P2.h
yP2.cpp
P3.h
yP3.cpp
P4.h
yP4.cpp
P5.h
yP5.cpp
P6.h
yP6.cpp
P7.h
yP7.cpp
P8.h
yP8.cpp
P9.h
yP9.cpp
P10.h
yP10.cpp
Crear la función template input
que simula el funcionamiento de la función de python input
.
Use Case:
// Por default el template retorna un std::string
auto text = input();
auto entero = input<int>("Ingrese un numero: ");
auto real = input<double>("Ingrese un numero: ");
std::cout << "El texto es: " << text << endl;
std::cout << "El entero es: " << entero << endl;
std::cout << "El real es: " << real << endl;
Crear la función template print
que permita imprimir el contenido de un contenedor, incluyendo un delimitador, un objeto del tipo std::ostream
que recibirá el contenido del contenedor.
Use Case:
// Vector
std::vector<int> vec = {10, 20, 30, 40, 50, 60};
// Imprimir en consola
print(begin(vec), end(vec), std::cout, "-");
// Grabarlos en un archivo
std::ofstream file("out.txt");
print(begin(vec), end(vec), file, "|");
// Imprimir la mitad de valores
auto last_it = next(begin(vec), vec.size() / 2);
print(begin(vec), last_it, std::cout, "-");
Crear la función template sumarizar
que permita sumar el contenido de un contenedor con valores numéricos, que incluya un parámetro que defina un valor inicial.
Use Case:
// Contenedor
std::list<double> lst = {10.5, 20.4, 30.2, 40.5, 50.9, 60.5};
cout << "Total: " << sumarizar(begin(lst), end(lst), 0) << endl;
// Calcular la mitad de valores inferior
auto last_it = next(begin(lst), size(lst) / 2);
cout << "Sumatoria de la mitad: " << sumarizar(begin(lst), last_it, 0) << endl;
Crear la clase template smart_ptr
que simule un puntero inteligente (la memoria es liberada automáticamente) y la función template make_smart_ptr
que simule el operador new
. Sobrecargar el operador de-referencia *
, el operador arrow ->
.
Use Case #1:
smart_ptr<int> sp1; // puntero inteligente no inicializado
sp1 = make_smart_ptr<int>(10);
cout << *sp1 << endl; // Imprimiendo el contenido
// puntero inteligente no inicializado
smart_ptr<string> sp2 = make_smart_ptr<string>("Hola");
cout << *sp2 << endl;
Use Case #2:
class point {
int x;
int y;
public:
point(int x, int y): x{x}, y{y} {}
point() = default;
friend ostream& operator<< (ostream& os, const point& p) {
os << "{" << x <<", " << y << "}" << endl;
return os;
}
int get_x() { return x; }
int get_y() { return y; }
};
smart_ptr<point> sp1; // puntero inteligente no inicializado
sp1 = make_smart_ptr<point>(20, 30);
cout << *sp1 << endl; // Imprimiendo el contenido
smart_ptr<point> sp2 = make_smart_ptr<point>(10, 40); // puntero inteligente no inicializado
cout << sp2->get_x() << endl;
cout << sp2->get_y() << endl;
Crear la función template suma_producto
del tipo variadic que permita tomar de 2 en 2 los parámetros de la función template, calcule el producto y que realice la suma de todos los productos. En caso la cantidad de valores variados sea impar el último valor será considerado en la suma.
Use Case #1:
std::cout << suma_producto(1, 10, 3, 5) << endl; // El resultado seria: 25
Use Case #2:
std::cout << suma_producto(1) << endl; // El resultado seria: 1
Use Case #3:
std::cout << suma_producto(2, 10.5, 14.0, 1, 11.0) << endl; // El resultado seria: 46
Use Case #4:
std::cout << suma_producto(-2, 0, 1, 0, 0) << endl; // El resultado seria: 0
Crear la función template index_of
que retorne la posición del tipo de dato del parámetro de la funcion, comparado con una lista de tipos, en caso el tipo no se encuentra entonces la funcion retornara -1.
Use Case #1:
char var1{};
std::cout << index_of<int, char>(var1) << endl; // El resultado seria: 1
Use Case #2:
string var2;
std::cout << index_of<int, char, double, float, string>(var2) << endl; // El resultado seria: 4
Use Case #3:
vector<int> var3;
std::cout << index_of<int, char, vector<int>, list<double>>(var3) << endl; // El resultado seria: 2
Use Case #4:
vector<double> var4;
std::cout << index_of<int, char, vector<int>, list<double>>(var4) << endl; // El resultado seria: -1
La librería de C++ no permite usar directamente el operador std::cout
de forma similar que en el caso de variables simples, por ejemplo:
int var = 20
std::cout << "El valor de var es: " << var << std::endl; // El valor de var es: 20
En cambio en contenedores por ejemplo del tipo std::array
, std::vector
, std::list
o std::map
no permite por ejemplo:
std::list<int> lst = {10, 20, 30};
std::cout << "Los valores de lst son: " << lst << std::endl; // NO PERMITIDO
std::map<char, int> mp = {{'a', 10}, {'b', 20}, {'c', 30}};
std::cout << "Los valores de mp son: " << mp << std::endl; // NO PERMITIDO
Desarrollo el template de sobrecarga del operador <<
que permita generalizar el uso de std::cout
para el caso de los siguientes contenedores:
std::array
std::vector
std::list
std::map
Use Case #1:
std::array<int, 3> arr = {10, 20, 30};
std::cout << "Los valores de arr son: " << arr << std::endl; // Los valores de lst son: {10, 20, 30}
Use Case #2:
std::vector<int> vec = {10, 20, 30};
std::cout << "Los valores de vec son: " << vec << std::endl; // Los valores de lst son: {10, 20, 30}
Use Case #3:
std::list<int> lst = {10, 20, 30};
std::cout << "Los valores de lst son: " << lst << std::endl; // Los valores de lst son: {10, 20, 30}
Use Case #4:
std::map<char, int> mp = {{'a', 10}, {'b', 20}, {'c', 30}};
std::cout << "Los valores de mp son: " << mp << std::endl; // Los valores de mp son: {{a: 10}, {b: 20}, {c: 30}}
Generar un template funcion are_same
que verifique si todos los tipos de una lista de tipos son iguales.
Use Case #1:
cout << boolalpha << are_same<int>() << endl; // true
Use Case #2:
cout << boolalpha << are_same<int, int , char>() << endl; // false
Use Case #3:
cout << boolalpha << are_same<vector<int>, vector<int> , vector<int>>() << endl; // true
Use Case #4:
cout << boolalpha << are_same<int, const int, int&, int &&>() << endl; // false
Generar un template función init_array
que inicie un arreglo estático de cualquier tipo y tamaño.
Use Case #1:
int arreglo[10];
init_array(arreglo); // Valor inicial 0
for (const auto& i: arreglo)
std::cout << i << " ";
std::cout << std::endl;
// output: 0 1 2 3 4 5 6 7 8 9
Use Case #2:
int arreglo[15];
init_array(arreglo, 5); // Se puede configurar el valor inicial (5)
for (const auto& i: arreglo)
std::cout << i << " ";
std::cout << std::endl;
// output: 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Use Case #3:
float arreglo[14];
init_array(arreglo, 1, 3); // Se puede configurar el valor inicial (1) y
// el paso (3)
for (const auto& i: arreglo)
std::cout << i << " ";
std::cout << std::endl;
// output: 1 4 7 10 13 16 19 22 25 28 31 34 37 40
Use Case #4:
double arreglo[] {0, 0, 0, 4, 5, 6};
init_array(arreglo, 2, 8, 2); // Se puede configurar el valor inicial (2)
// valor siguiente al final (8) y
// el paso (2)
for (const auto& i: arreglo)
std::cout << i << " ";
std::cout << std::endl;
// output: 2 4 6 4 5 6
Desarrollar el template de clase searcher
que permita ordenar los valores al momento de crear el research o al momento de asignarle un arreglo o contenedor y realice la búsqueda de la posición de un valor en un contenedor del tipo secuencia como:
std::array
std::vector
En caso el valor no sea encontrado, la posición que se devolverá será -1.
Use Case #1:
array<int, 4> arr = { 40, 10, 25, 20 };
searcher<array<int, 4>> s = arr;
for (const auto& i: arr)
cout << i << " ";
cout << endl; // 10 20 25 40
auto index = (s << 10);
cout << index << endl; // 0
Use Case #2:
vector<int> vec = {5, 1, 2, 3, 5, 7, 7};
searcher<vector<int>> s = vec;
for (const auto& i: vec)
cout << i << " ";
cout << endl; // 1 2 3 5 5 7 7
cout << (s << 10) << endl; // -1
Use Case #3:
vector<double> vec = {5, 1, 2, 3, 5, 4, 7, -1};
searcher<vector<double>> s = vec;
for (const auto& i: vec)
cout << i << " ";
cout << endl; // -1 1 2 3 4 5 5 7
cout << (s << 3) << endl; // 3
Use Case #4:
array<float, 8> arr = {-1, 1, 2, 3, 5, 4, 7, 8};
searcher<array<float, 8>> s = arr;
for (const auto& i: arr)
cout << i << " ";
cout << endl; // -1 1 2 3 4 5 7 8
cout << (s << 2) << endl; // 2