-1

I need some help with a linker error that i solved but i cannot explain why

This is my code beginning with my program.h file:

    #pragma once

    #include <vector>
    #include <string>
    #include <fstream>

    template<class T> class InputData
    {
    public:
        InputData(std::string);
        void storeDataFromSourceFile();
        void putDataFromSourceFileIntoVector(std::vector<T>);
    private:
        void inputLocationOfSourceFile();

        void setSourceFileToLocation();

        std::vector<T> inputVector;
        std::string locationOfInputFile;
        std::fstream sourceFile;
    };

This was the corresponding program.cpp code:

#include <vector>
#include <string>
#include <fstream>

#include "InputData.h"

template<class T> InputData<T>::InputData(std::string source = "")
{
    this->locationOfInputFile = source;
    if (locationOfInputFile != "")
        this->sourceFile.open(locationOfInputFile);
}

template<class T> void InputData<T>::inputLocationOfSourceFile()
{
    std::cout << "Please enter location of source file";
    std::cin >> this->locationOfInputFile;
}

template<class T> void InputData<T>::setSourceFileToLocation()
{
    if (this->locationOfInputFile == "")
        this->inputLocationOfSourceFile();
    this->sourceFile.open(this->locationOfInputFile);
}

template<class T> void InputData<T>::storeDataFromSourceFile()
{
    T inputElement;
    if (this->locationOfInputFile == "")
        this->setSourceFileToLocation();
    while (this->sourceFile >> inputElement)
        this->inputVector.push_back(inputElement);
}

template<class T> void InputData<T>::putDataFromSourceFileIntoVector(std::vector<T> destinationVector)
{
    destinationVector = this->inputVector;
}

This is my main function in the main.cpp

#include <string>
#include <iostream>
#include <vector>

#include "InputData.h"

void printVector(std::vector<int> vectorToPrint)
{
    for (std::vector<int>::const_iterator i = vectorToPrint.begin(); i != vectorToPrint.end(); ++i)
        std::cout << *i << ' ';
}

int main()
{
    InputData<int> sourceOfIntegers("Input.txt");
    std::vector<int> destinationVector;
    sourceOfIntegers.storeDataFromSourceFile();
    sourceOfIntegers.putDataFromSourceFileIntoVector(destinationVector);
    printVector(destinationVector);
}

When i built the program with visual c++ 2013 these were the errors:

error LNK2019: unresolved external symbol "public: __thiscall InputData<int>::InputData<int>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??0?$InputData@H@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function _main
error LNK2019: unresolved external symbol "public: void __thiscall InputData<int>::storeDataFromSourceFile(void)" (?storeDataFromSourceFile@?$InputData@H@@QAEXXZ) referenced in function _main
error LNK2019: unresolved external symbol "public: void __thiscall InputData<int>::putDataFromSourceFileIntoVector(class std::vector<int,class std::allocator<int> >)" (?putDataFromSourceFileIntoVector@?$InputData@H@@QAEXV?$vector@HV?$allocator@H@std@@@std@@@Z) referenced in function _main

This was resolved by moving the function definitions from the program.cpp to the program.h and everything works.

I have checked online for reasons for this error but for some reasons the explanation for my particular code still eludes me.

Can you please give me a specific explanation of why this has happened?

PS: Also checked What is an undefined reference/unresolved external symbol error and how do I fix it? but still can't find a really logical explanation.

Community
  • 1
  • 1
ciprianr
  • 191
  • 1
  • 1
  • 15
  • 1
    You are using templates. Your solution *is* the correct solution, and that is to move the implementation to the header. http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – PaulMcKenzie Jan 21 '15 at 10:36
  • @PaulMcKenzie Thank you, this was the answer i was looking for. – ciprianr Jan 21 '15 at 10:38

2 Answers2

0

When you declared your class, you didn't prototype your methods to return the templatized variants. So when it read your class declaration and tried to find the expected functions, it failed.

Rubix Rechvin
  • 571
  • 3
  • 16
0

The reason is templates are too hi-level constructs for standard compiling and linking tools.

One of goals in the design of C++ was backward compatibility. link.exe can only link "machine code", but templates are "half-generated code". So you need implement all of your template methods in header files. Compilers will find them and compile.

Mark Shevchenko
  • 7,937
  • 1
  • 25
  • 29