Inferência de Tipo em C++

por Fabio A. Mazzarino

A inferência de tipo foi adicionada na versão C++11 através da palavra reservada auto. Através da inferência de tipo é possível deixar que o tipo da variável seja determinada em tempo de compilação conforme a sua inicialização.

Tipos Básicos

Vamos fazer um teste com tipos básicos:

auto x = 4;
auto y = 3.1415;
auto p = &x;

std::cout << "x type: " << typeid(x).name() << std::endl;
std::cout << "y type: " << typeid(y).name() << std::endl;
std::cout << "p type: " << typeid(p).name() << std::endl;

O trecho de código acima vai retornar a seguinte saída:

i
d
Pi

Indicando, respectivamente, int, double e int*. Ou seja, os tipos foram inferidos corretamente.

Tipos Extensos

Uma das forças do auto é evitar declarações de variáveis extensas, como por exemplo subclasses de templates:

std::set<std::string> names;
names.insert({"Bilbo", "Frodo", "Samwise", "Pippin"});
for (auto it = names.begin(); it != names.end(); it++) {
    if (it != names.begin())
        std::cout << ", ";
    std::cout << *it;
}
std::cout << std::endl;

No caso acima auto simplifica a declaração de std::set<std::string>::iterator, reduzindo a quantidade de código e reduzindo a possibilidades de erros. A saída será a seguinte:

Bilbo, Frodo, Pippin, Samwise

Outra opção é a definição de ponteiros para funções:

int sum(int x1, int x2, int x3, int x4, int x5) {
    return x1 + x2 + x3 + x4 + x5 + x6;
}
int main() {
    int (*p)(int, int, int, int, int) = sum;
    auto a = sum;
    std::cout << "typeid(p).name(): " << typeid(p).name() << std::endl;
    std::cout << "typeid(a).name(): " << typeid(a).name() << std::endl;
}

Que entrega a saída:

typeid(p).name(): PFiiiiiiE
typeid(a).name(): PFiiiiiiE

Note a diferença da complexidade da declaração dos ponteiros p e a.

decltype

decltype é a função interna de C e C++ utilizada para recuperar o tipo de declaração de uma variável. Por exemplo:

int x = 5;
decltype(x) j = x;
std::cout << "typeid(j).name(): " << typeid(j).name() << std::endl;

Que retornará a seguinte saída:

typeid(j).name(): i

Esse foi o básico de inferência de tipo, ainda há muito para estudar, mas vai ser suficiente pro próximo post.