Search code examples
c++templatesfunction-templatesredefinition

C++ function template specialization, function redefinition error


So, I have an assignment for college to create templates for these functions and ive done it by the instructions.. However, the fillDefault, which I had to make a specialization for int doesnt work. I get an error "multiple definition of `void fillDefault(std::vector<int, std::allocator >&, int)'.. What can I do?

//
// Created by irept on 22/04/2023.
//

#ifndef NALOGA_7_VECTORUTIL_H
#define NALOGA_7_VECTORUTIL_H

#include <vector>
#include <iostream>
#include <random>

template<typename T>
void fillDefault(std::vector<T>& vektor, int n){
    vektor.resize(n);
    for(int i=0; i<n; i++){
        vektor[i]=T();
    }
}

template<typename T>
void print(std::vector<T>& vektor){
    for(int i=0; i<vektor.size(); i++){
        std::cout << vektor[i] << " ";
    }
    std::cout << std::endl;
}

template<typename T>
void reverse(std::vector<T>& vektor){
    int j=0;
    std::vector<T> reverse(vektor.size());
    for(int i=vektor.size(); i>0; i--){
        reverse[j]=vektor[i-1];
        j++;
    }
    for(int i=0; i<vektor.size(); i++){
        vektor[i]=reverse[i];
    }
}

template<typename T>
std::vector<T> mergeVectors(std::vector<std::vector<T>>& vektorVektorjev){
    std::vector<T> merged;
    for(int i=0; i<vektorVektorjev.size(); i++){
        merged.insert(merged.end(), vektorVektorjev[i].begin(), vektorVektorjev[i].end());
    }
    return merged;
}

template<>
void fillDefault(std::vector<int>& vektor, int n){
    for(int i=0; i<n; i++){
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<int> dist (1, 100);
        int value=dist(gen);
        vektor.push_back(value);
    }
}
#endif //NALOGA_7_VECTORUTIL_H

I tried moving the definition into the .cpp file like chatgpt said, but that resulted in other errors.


Solution

  • The problem is that an explicit specialization behaves as a non templated entity so that you can either move the explcit specialization into a source file or use the keyword inline when using it in header file. That is, there are 2 ways to solve this problem, both of which are shown below.

    Method 1

    One way to solve this is to add the keyword inline when specializing the function template as shown below:

    header.h

    //other code as before
    
    template<>
    vvvvvv---------------------------------------------------->added this inline keyword
    inline void fillDefault(std::vector<int>& vektor, int n){
        //other code as before
    }
    

    working demo


    Method 2

    Second option is to move the specialization into a source file as shown below:

    source.cpp

    #include"header.h"
    
    template<>
    inline void fillDefault(std::vector<int>& vektor, int n){
        for(int i=0; i<n; i++){
            std::random_device rd;
            std::mt19937 gen(rd());
            std::uniform_int_distribution<int> dist (1, 100);
            int value=dist(gen);
            vektor.push_back(value);
        }
    }
    
    

    working demo