0

There are some known linking issues when trying to separate a template class into header & implementation files. This page has several solutions, and so does this SO post, although neither address defining functions which involve the template though. In particular I am struggling to overload << into std::ostream

// include/valueStorer.h
#ifndef VALUE_STORER_H
#define VALUE_STORER_H

template <class T>
class ValueStorer
{
    T value;
public:
    ValueStorer(T);
    void setValue(T);
    T getValue();
};

#endif // #ifndef VALUE_STORER_H


// src/valueStorer.cpp
#include "valueStorer.h"

template <class T>
ValueStorer<T>::ValueStorer(T v) 
{
    value = v;
}

template <class T>
void ValueStorer<T>::setValue(T newValue) 
{
    value = newValue;
}

template <class T>
T ValueStorer<T>::getValue()
{
    return value;
}

template class ValueStorer<double>;


// src/main.cpp
#include <iostream>

#include "ValueStorer.h"

int main()
{
    ValueStorer<double> foo(3.14);

    std::cout << "Value in foo is " << foo.getValue() << std::endl;

    foo.setValue(4.2);
    std::cout << "Value in foo is " << foo.getValue() << std::endl;
}

I compile the above with

g++ -c src/valueStorer.cpp -I include -o build/valueStorer.o

And main links and executes fine. I am unable to add an overload to operator<< however:

// include/valueStorer.h (addition)

template <class T>
std::ostream &operator<< (std::ostream &, const ValueStorer<T> &);


// src/valueStorer.cpp (addition)
template <class T>
std::ostream &operator<< (std::ostream &os, const ValueStorer<T> &vs)
{
    os << "Value is " << vs.getValue();
    return os;
}

I can compile the implementation file fine but cannot link with main (which now calls <<):

g++ src/main.cpp build/valueStorer.o -I include -o bin/program

main.cpp:(.text+0x3e): undefined reference to `std::ostream& operator<< <double>(std::ostream&, ValueStorer<double> const&)'
/usr/bin/ld: main.cpp:(.text+0x69): undefined reference to `std::ostream& operator<< <double>(std::ostream&, ValueStorer<double> const&)'
collect2: error: ld returned 1 exit status

Do I need to implement each of these overloads separately?

mcindoe
  • 101
  • 2
  • 8
  • The duplicate question -- which you were already aware of -- explains why template implementations should be in headers, and you are putting the implementation into a `.cpp` file instead, and have the expected problem. So, what is your question, exactly? – Sam Varshavchik Jan 09 '21 at 13:52
  • @SamVarshavchik the top answer on the duplicate question states that this is not the case. I am seeking a workaround to putting the template implementation in headers, three suggestions are provided in the linked article and Method 1 of these is provided in the top answer of the duplicate question. My question shows that I am aware of this and am struggling specifically with the syntax of defining a function which involves the class template as in the operator<<, which is not addressed in either the article or the SO question – mcindoe Jan 09 '21 at 13:56
  • Question is answered in https://stackoverflow.com/questions/115703/storing-c-template-function-definitions-in-a-cpp-file?rq=1 however so it's indeed a duplicate. Perhaps can update the duplicate marking which I don't think answers the question, or I can delete – mcindoe Jan 09 '21 at 14:20

0 Answers0