1

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?

Niall
  • 30,036
  • 10
  • 99
  • 142
GChamon
  • 456
  • 5
  • 12
  • update: if I cut out the static from the CRTP everything Works fine, but then each derived class object will have its own vector memory, and it breaks my goal – GChamon Nov 15 '14 at 20:20
  • 1
    The member `template<> vector subSeq::memory;` should be defined somewhere. To achieve your desired result, you should do this explicitly yourself in only a single translation unit (cpp file). If you wish to use implicit instantiations, note this answer for more detail on common symbols http://stackoverflow.com/a/16005504/3747990 – Niall Nov 15 '14 at 20:35
  • 1
    cool! template vector subSeq::memory = {}; works fine, and it seems I achieved the result. I was quite unsure how to define the vector, but it Works. Would you add the comment as an answer or should I do it? – GChamon Nov 15 '14 at 20:43
  • try using (typename memory) ? It will tell the compiler that memory does exist. – Lectem Nov 15 '14 at 20:54
  • using typename I wouldn't have to define the static variable somewhere else? – GChamon Nov 15 '14 at 21:02

1 Answers1

2

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.

Community
  • 1
  • 1
Niall
  • 30,036
  • 10
  • 99
  • 142
  • thanks for the edit. I am not a native english speaker, sometimes I make such awful mistakes. Plus i'm still getting the hang of using stack overflow. – GChamon Nov 15 '14 at 21:49
  • @GChamon, no problem. Your question had a nice twist to it – Niall Nov 15 '14 at 22:04