Desafio C++

Soma de arrays com template e instanciação explícita

Enunciado

Crie um template de função somarArray que recebe um ponteiro para o primeiro elemento de um array, um índice inicial e um índice final (exclusivo), e retorna a soma dos elementos no intervalo. A função deve funcionar para int, double e float. No main, crie arrays desses três tipos e chame a função para cada um, imprimindo as somas. Além disso, force uma instanciação explícita para int usando template double somarArray<double>(double*, int, int); (ou similar) para demonstrar o conceito.

Requisitos

  • A função deve ser um template com template<typename T>.
  • Deve somar os elementos do índice inicio até fim - 1.
  • Deve funcionar para int, double e float.
  • O main deve chamar a função para os três tipos e imprimir as somas.
  • Deve haver uma instanciação explícita de pelo menos um tipo.

Código inicial

#include <iostream>

// TODO: template somarArray

int main() {
    // TODO: crie arrays e chame somarArray
    return 0;
}

Saída esperada

Soma int: 15
Soma double: 6.6
Soma float: 7.5
Ver dica

Use um loop for (int i = inicio; i < fim; ++i) e acumule em uma variável T soma = T{};. A instanciação explícita pode ser feita com template double somarArray<double>(double*, int, int); fora do main.

Mostrar solução
#include <iostream>

// Template genérico: soma elementos de um array no intervalo [inicio, fim)
template<typename T>
T somarArray(T* arr, int inicio, int fim) {
    T soma = T{};  // inicializa com zero do tipo T
    for (int i = inicio; i < fim; ++i) {
        soma += arr[i];
    }
    return soma;
}

// Instanciação explícita para double (demonstra o conceito)
template double somarArray<double>(double*, int, int);

int main() {
    int ints[] = {1, 2, 3, 4, 5};
    double doubles[] = {1.1, 2.2, 3.3};
    float floats[] = {1.5f, 2.5f, 3.5f};

    // Dedução: T = int
    std::cout << "Soma int: " << somarArray(ints, 0, 5) << '\n';
    // Dedução: T = double (também instanciada explicitamente acima)
    std::cout << "Soma double: " << somarArray(doubles, 0, 3) << '\n';
    // Dedução: T = float
    std::cout << "Soma float: " << somarArray(floats, 0, 3) << '\n';

    return 0;
}

Passo a passo

  1. Declaramos o template somarArray com template<typename T>, que aceita um ponteiro T*, e dois índices inicio e fim.
  2. Inicializamos T soma = T{}; para garantir que a soma comece com o valor zero do tipo T (0 para int, 0.0 para double, etc.).
  3. O loop for (int i = inicio; i < fim; ++i) percorre o intervalo semiaberto [inicio, fim).
  4. Dentro do loop, acumulamos soma += arr[i];.
  5. Após o loop, retornamos soma.
  6. Fora do main, escrevemos template double somarArray<double>(double*, int, int); para forçar a instanciação explícita para double, mesmo que já ocorra implicitamente.
  7. No main, criamos três arrays e chamamos somarArray para cada um. O compilador deduz T a partir do tipo do ponteiro.
  8. As somas são impressas com os rótulos corretos.

Por que funciona

O template permite que a mesma lógica de soma seja aplicada a diferentes tipos numéricos. A dedução de tipos determina T a partir do ponteiro passado. A instanciação explícita força a geração do código para double antes mesmo de ser usada, o que pode ser útil para reduzir o tempo de compilação em projetos grandes ou para exportar templates em bibliotecas. A especialização não foi necessária aqui, mas o conceito de instanciação é demonstrado.

Erros comuns

  • Esquecer de inicializar soma com T{}: se usar T soma;, o valor inicial é indefinido, gerando resultados errados.
  • Passar o tamanho errado do array: se fim for maior que o número de elementos, o programa acessa memória inválida.
  • Declarar a instanciação explícita dentro do main: isso não é permitido; deve ser feita no escopo global ou de namespace.
  • Usar int para acumular double: se soma fosse int, a parte fracionária seria perdida. O tipo T garante a precisão correta.

Outra forma de resolver

Se quiser evitar ponteiros crus, pode usar std::vector<T> e iteradores:

template<typename T>
T somarArray(const std::vector<T>& v, int inicio, int fim) {
    T soma = T{};
    for (int i = inicio; i < fim; ++i) soma += v[i];
    return soma;
}

Isso é mais seguro e idiomático em C++ moderno, mas exige incluir <vector>.

Saída esperada

Soma int: 15
Soma double: 6.6
Soma float: 7.5