Implementing CRTP and issue with "undefined reference"

1k Views Asked by At

I have the goal to make a base class, and a CRTP subbase class containing a static vector that will hold different values for each Derived class. However each object from the derived class must be able to see only one vector for the entire class. Moreover, I need to manipulate this vector through a common interface, this is why I am setting up a Base class.

Base class and subbase

class Seq {
public:
    virtual unsigned long int elem(int i) = 0;
    virtual void print(ostream& os) =0; // print out to a ostream
    virtual int length() const =0;// return size of vector
    virtual ~Seq() {}
protected:
    virtual void gen_elems(int i) = 0; //generates elements
};

template<class T>
class subSeq: public Seq {
public:
    unsigned long int elem(int i);
    void print(ostream& os);
    int length() const {return (int)memory.size();}
    virtual ~subSeq() {}
protected:
    static vector<long int> memory;
    virtual void gen_elems(int i) = 0;
};

template<class T>
void subSeq<T>::print(ostream& os) {
    if((int)memory.size() != 0) {
        cout << "Stored numbers: ";
        for(int i=0; i<(int)memory.size(); i++) {
            os << memory[i] << " ";
        }
        cout << "\n";
    } else {
        cout << "Empty class!!\n";
    }
}

template<class T>
unsigned long int subSeq<T>::elem(int i) {
    if( i>=(int)memory.size() ) gen_elems(i);
    return memory[i];
}

One of my derived classes:

class Fibonnacci: public subSeq<Fibonnacci> {
public:
    Fibonnacci(int=0);
    ~Fibonnacci() {}
protected:
    void gen_elems(int i); // Gera os elementos da série até o iésimo elemento (protected)
};

and its implementation:

Fibonnacci::Fibonnacci(int param) { if(param) gen_elems(param); }

void Fibonnacci::gen_elems(int param) {

    for(int i=(int)memory.size(); i<param; i++) {
        if(i>1) memory.push_back((long int)memory[i-1]+memory[i-2]);
        else memory.push_back(1);
    }

}

the problem occurs around this line

if(i>1) memory.push_back((long int)memory[i-1]+memory[i-2]);

compiler yells at me for

undefined reference to `subSeq<Fibonnacci>::memory'

this has been going on for hours, and since I am new to the concept CRTP, I see I don't understand it well and need help of people more capable than me.

Could someone enlighten me to what the problem is?

1

There are 1 best solutions below

2
On BEST ANSWER

The member

template <>
vector<long int> subSeq<Fibonnacci>::memory;

Should be defined somewhere. To achieve your desired result, you should do this explicitly yourself in only a single translation unit (cpp file).

Or alternatively;

template <class T>
vector<long int> subSeq<T>::memory = {};

As some compilers do support common data folding (e.g COMDAT in msvc) which may help if you wish to use implicit instantiations, note this answer for more detail on common symbols.