"Undefined symbols" linker error with simple template class
Asked Answered
A

4

24

Been away from C++ for a few years and am getting a linker error from the following code:

Gene.h

#ifndef GENE_H_INCLUDED
#define GENE_H_INCLUDED

template <typename T>
class Gene {
    public:
    T getValue();
    void setValue(T value);
    void setRange(T min, T max);

    private:
    T value;
    T minValue;
    T maxValue;
};

#endif // GENE_H_INCLUDED

Gene.cpp

#include "Gene.h"

template <typename T>
T Gene<T>::getValue() {
    return this->value;
}

template <typename T>
void Gene<T>::setValue(T value) {
    if(value >= this->minValue && value <= this->minValue) {
        this->value = value;
    }
}

template <typename T>
void Gene<T>::setRange(T min, T max) {
    this->minValue = min;
    this->maxValue = max;
}

Using Code::Blocks and GCC if it matters to anyone. Also, clearly porting some GA stuff to C++ for fun and practice.

Apprehensive answered 16/6, 2009 at 2:34 Comment(2)
Exact error messages would be helpful.Ca
possible duplicate of Why can templates only be implemented in the header file?Uniat
F
31

The template definition (the cpp file in your code) has to be included prior to instantiating a given template class, so you either have to include function definitions in the header, or #include the cpp file prior to using the class (or do explicit instantiations if you have a limited number of them).

Futuristic answered 16/6, 2009 at 2:40 Comment(2)
Thanks! I must have learned that at one point. Maybe now it will stick :DApprehensive
Or just implement the whole template in the header file. See the related question Why can templates only be implemented in the header file?Participle
C
5

Including the cpp file containing the implementations of the template class functions works. However, IMHO, this is weird and awkward. There must surely be a slicker way of doing this?

If you have only a few different instances to create, and know them beforehand, then you can use "explicit instantiation"

This works something like this:

At the top of gene.cpp add the following lines

template class Gene<int>;
template class Gene<float>;
Cogency answered 11/9, 2009 at 14:39 Comment(0)
V
1

In if(value >= this->minValue && value <= this->minValue) the second minValue should be maxValue, no?

Echo what Sean said: What's the error message? You've defined and declared the functions, but you've not used them in anything anywhere, nor do I see an error (besides the typo).

Virnelli answered 31/10, 2011 at 13:20 Comment(0)
E
1

TLDR

It seems that you need an Explicit Instantiation i.e. to actually create the class. Since template classes are just "instructions" on how to create a class you actually need to tell the compiler to create the class. Otherwise the linker won't find anything when it goes looking.

The thorough explanation

When compiling your code g++ goes through a number of steps the problem you're seeing occurs in the Linking step. Template classes define how classes "should" be created, they're literally templates. During compile time g++ compiles each cpp file individually so the compiler sees your template on how to create a class but no instructions on what "classes" to create. Therefore ignores it. Later during the linking step the g++ attempts to link the file containing the class (the one that doesn't exist) and fails to find it ultimately returning an error.

To remedy this you actually need to "explicitly instantiate" the class by adding the following lines to Gene.cpp after the definition of the class

template class Gene<whatever_type_u_wanna_use_t>;int

Check out these docs I found them to be super helpful.

Excrement answered 13/10, 2022 at 18:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.