Olá pessoal. Tudo certo?!
Seguimos mostrando os fundamentos de C++. Hoje, mostro como utilizar Function Templates e Class Templates.
Se você está chegando agora, considere consultar o índice de séries.
Pouco texto, algum código. Veja:
#include <iostream>
template<typename T> T max(T left, T right)
{
return (left > right) ? left : right;
}
template<typename T> T max(T xs[], int lenxs)
{
T result = xs[0];
for (int i = 1; i < lenxs; i++)
result = max(result, xs[i]);
return result;
}
void main()
{
int ints[] = {1, 3, 9, 2};
long longs[] = {9, 45, 23, 12};
double doubles[] = {2.0, 7.5, 0.45};
int lenints = sizeof(ints) / sizeof ints[0];
int lenlongs = sizeof(longs) / sizeof longs[0];
int lendoubles = sizeof(doubles) / sizeof(doubles[0]);
std::cout
<< "max(ints) : " << max(ints, lenints) << std::endl
<< "max(longs) : " << max(longs, lenlongs) << std::endl
<< "max(doubles): " << max(doubles, lendoubles) << std::endl;
}
O que temos aqui? Function Templates. Em termos de sintaxe, parece muito com Generics do C#. Entretanto, a implementação é bem diferente.
Templates são resolvidos em tempo de compilação. Ou seja, sempre que um “function template” é requisitado, uma nova função é escrita no resultado compilado.
Templates também podem ser utilizados com classes. Veja:
#include <iostream>
template<typename T>
class Numbers
{
public:
static T max(T left, T right)
{
return (left > right) ? left : right;
};
static T max(T xs[], int lenxs)
{
T result = xs[0];
for (int i = 1; i < lenxs; i++)
result = max(result, xs[i]);
return result;
};
};
void main()
{
int ints[] = {1, 3, 9, 2};
long longs[] = {9, 45, 23, 12};
double doubles[] = {2.0, 7.5, 0.45};
int lenints = sizeof(ints) / sizeof ints[0];
int lenlongs = sizeof(longs) / sizeof longs[0];
int lendoubles = sizeof(doubles) / sizeof(doubles[0]);
std::cout
<< "max(ints) : " << Numbers<int>::max(ints, lenints) << std::endl
<< "max(longs) : " << Numbers<long>::max(longs, lenlongs) << std::endl
<< "max(doubles): " << Numbers<double>::max(doubles, lendoubles) << std::endl;
}
Pegou a idéia? A utilização lembra muito Generics do C#. Não acha?! Mas, lembre-se, a implementação é diferente
Obviamente, podemos usar templates para gerar classes com membros não-estáticos. Veja:
#include <iostream>
template<typename T>
class NumbersSet
{
public:
NumbersSet(T* xs, int lenxs)
{
_xs = xs;
_lenxs = lenxs;
}
T max()
{
T result = _xs[0];
for (int i = 1; i < _lenxs; i++)
result = max(result, _xs[i]);
return result;
};
private:
T* _xs;
int _lenxs;
static T max(T left, T right)
{
return (left > right) ? left : right;
};
};
void main()
{
int ints[] = {1, 3, 9, 2};
long longs[] = {9, 45, 23, 12};
double doubles[] = {2.0, 7.5, 0.45};
int lenints = sizeof(ints) / sizeof ints[0];
int lenlongs = sizeof(longs) / sizeof longs[0];
int lendoubles = sizeof(doubles) / sizeof(doubles[0]);
std::cout
<< "max(ints) : " << NumbersSet<int>(ints, lenints).max() << std::endl
<< "max(longs) : " << NumbersSet<long>(longs, lenlongs).max() << std::endl
<< "max(doubles): " << NumbersSet<double>(doubles, lendoubles).max() << std::endl;
}
Templates, em C++ não se restringem apenas a tipos. Podemos especificar qualquer constante. Veja:
#include <iostream>
template<typename T, int lenxs>
class NumbersSet2
{
public:
NumbersSet2(const T xs[])
{
for (int i = 0; i < lenxs; i++)
_xs[i] = xs[i];
}
T max()
{
T result = _xs[0];
for (int i = 1; i < lenxs; i++)
result = max(result, _xs[i]);
return result;
};
private:
T _xs[lenxs];
static T max(T left, T right)
{
return (left > right) ? left : right;
};
};
void main()
{
int ints[] = {1, 3, 9, 2};
long longs[] = {9, 45, 23, 12};
double doubles[] = {2.0, 7.5, 0.45};
std::cout
<< "max(ints) : " << NumbersSet2<int, 4>(ints).max() << std::endl
<< "max(longs) : " << NumbersSet2<long, 4>(longs).max() << std::endl
<< "max(doubles): " << NumbersSet2<double, 3>(doubles).max() << std::endl;
}
Certo?!
Era isso.
Pingback: C++ 101 – Parte 20 – Conhecendo o (deprecated) ‘auto_ptr’ « Elemar DEV