A STL
A STL (Standard Template Library) é uma das maiores forças do C++. Ela fornece containers eficientes, algoritmos genéricos e iteradores que permitem escrever código conciso e reutilizável. Este artigo mostra como usar templates no básico e como a STL resolve problemas comuns do dia a dia.
Motivação: sem templates
Section titled “Motivação: sem templates”Sem templates, precisaríamos escrever funções separadas para cada tipo, resultando em duplicação de código e dificuldade de manutenção.
int dobrar(int x) { return x * 2; }double dobrar(double x) { return x * 2; }
int main() { std::cout << dobrar(2) << "\n"; std::cout << dobrar(2.5) << "\n";}Entendendo templates
Section titled “Entendendo templates”Templates permitem escrever código genérico que funciona com qualquer tipo. O compilador gera automaticamente as versões específicas necessárias.
template<typename T>T dobrar(T x) { return x * 2; }
int main() { std::cout << dobrar(2) << "\n"; // deduz int std::cout << dobrar(2.5) << "\n"; // deduz double}A dedução de tipo funciona automaticamente na maioria dos casos, mas você
pode especificar explicitamente com dobrar<int>(2) quando necessário.
As palavras-chave typename e class são equivalentes em templates
simples.
Classes também podem ser templates:
template<typename T>struct Caixa { T valor; };
int main() { Caixa<int> c{42}; Caixa<std::string> s{"oi"}; std::cout << c.valor << " " << s.valor << "\n";}A STL na prática
Section titled “A STL na prática”A STL oferece três componentes principais: containers para armazenar dados, iteradores para acessar esses dados, e algoritmos para manipulá-los.
Os containers essenciais incluem std::vector para arranjos dinâmicos,
std::string para texto, e std::unordered_map para dicionários de
chave-valor baseados em hash.
Prefira algoritmos da STL a loops manuais quando existir equivalente. Eles são otimizados e expressam a intenção claramente:
#include <vector>#include <algorithm>#include <numeric>#include <iostream>
int main() { std::vector<int> v{3,1,4,1,5}; std::sort(v.begin(), v.end()); int soma = std::accumulate(v.begin(), v.end(), 0); std::cout << soma << "\n";}O unordered_map funciona como um dicionário eficiente:
#include <unordered_map>#include <string>#include <iostream>
int main() { std::unordered_map<std::string,int> freq; for (auto s : {"um","um","dois"}) freq[s]++; std::cout << freq["um"] << " " << freq["dois"] << "\n";}Novidades modernas
Section titled “Novidades modernas”O C++17 introduziu std::string_view, uma visão leve sobre strings que
evita cópias desnecessárias:
#include <string_view>#include <iostream>
void print(std::string_view s) { std::cout << s << "\n"; }O C++20 trouxe a biblioteca <ranges>, permitindo pipelines elegantes com
views e algoritmos:
#include <ranges>#include <vector>#include <iostream>
int main() { using std::views::filter; using std::views::transform; std::vector<int> v{1,2,3,4,5,6}; auto evens_squared = v | filter([](int x){ return x % 2 == 0; }) | transform([](int x){ return x * x; }); for (int x : evens_squared) std::cout << x << "\n";}Também em C++20, std::span oferece uma visão segura sobre dados contíguos
sem assumir propriedade:
#include <span>#include <iostream>
void soma(std::span<const int> xs) { int s = 0; for (int x : xs) s += x; std::cout << s << "\n";}O método contains em unordered_map simplifica verificações:
#include <unordered_map>
bool tem(const std::unordered_map<int,int>& m, int k) { return m.contains(k); // C++20}O C++23 adicionou std::ranges::to para coletar resultados de pipelines
diretamente em containers:
#include <ranges>#include <vector>
int main() { std::vector<int> v{1,2,3,4}; auto out = v | std::views::transform([](int x){return x+1;}) | std::ranges::to<std::vector<int>>();}Boas práticas
Section titled “Boas práticas”Sempre inclua os headers corretos para cada componente da STL que utilizar.
Tenha cuidado pois inserções e remoções em containers podem invalidar
iteradores existentes. Use auto para simplificar tipos verbosos, e
auto& quando precisar modificar elementos durante iteração. A STL se
integra perfeitamente com smart pointers quando você precisa de
polimorfismo em containers.
Para compilar código com diferentes padrões:
- C++17:
g++ -std=c++17 arquivo.cpp -o exec - C++20:
g++ -std=c++20 arquivo.cpp -o exec - C++23:
g++ -std=c++23 arquivo.cpp -o exec