2

I have created a template class (ABase) and then extended that class (adding some extra functionality) to a derived class (A). The derived class is also specialized. However when I reference a member from the base class in the specialized derived class, I get a linker error that there is an undefined reference to the base class member.

The code layout is as follows:

ABase.h:

#include <vector>

namespace A {

template<typename T>
class ABase {
private:
    std::vector<T> items;
public:
    ABase(){};
    void addItem(T item);
};

}

ABase.cpp:

#include "ABase.h"

namespace A {

template<typename T>
void ABase<T>::addItem(T item) {
    items.push_back(item);
}

}

A.h:

#include <string>
#include "ABase.h"

namespace A {

class A : public ABase<std::string> {
public:
    void foo(std::string item);
};

}

A.cpp:

namespace A {

void A::foo(std::string item) {
    //do some extra stuff
    ABase::addItem(item);
}
template class ABase<std::string>;
}

main.cpp:

#include <string>
#include "A.h"

using namespace std;

int main() {
    A::A a;
    string item = "hello";
    a.foo(item);
}

I have searched for similar problems such as:

  1. Undefined reference to partial specialized template class function during link time
  2. Undefined reference to member function of template base class

Which recommend adding

template class ABase<std::string>;

to the bottom of the A.cpp, however as above I have tried this and it does not seem to work. What can I do to get this to link. It does compile, but returns:

./src/A.o: In function `A::A::foo(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
/test-proj/Debug/../src/A.cpp:14: undefined reference to `A::ABase<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::addItem(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status
make: *** [test-proj] Error 1

when it is linking. Thanks for your help!

Maxpm
  • 24,113
  • 33
  • 111
  • 170
Tony
  • 23
  • 2

1 Answers1

1

It should compile if you move the implementation of addItem into the ABase.h header. Something like so:

#include <vector>

namespace A 
{
    template<typename T>
    class ABase 
    {
        private:
            std::vector<T> items;
        public:
            ABase(){};
            void addItem(T item)
            {
                items.push_back(item);
            };
    };
}

The ABase.cpp file would then become redundant (unless you have other method implementations)

Brandon
  • 317
  • 1
  • 10
  • that works great but I would rather keep the implementation separate from the header. Is there any way I can solve the problem and keep the implementation out of the header? – Tony Sep 02 '15 at 12:25
  • not with templates there isn't – ruben.moor Nov 11 '22 at 23:44