0

So I have this interface here ...

template<typename T>
class SerdesTest {
public:
    virtual const char* type() = 0;
    virtual const char* serialize(const std::vector<T>&) = 0;
    virtual void deserialize(const char*) = 0;
    virtual bool test(const std::vector<T>&) = 0;
};

And I want to create an array of the interfaces and add different implementations like this ...

std::vector<std::unique_ptr<SerdesTest<long>>> tests{};
tests.push_back(std::unique_ptr<SerdesTest<long>>(new JSONSerdes<long>()));

This is the header of my impl class

...
#include "serdes_test.h"
...

template<typename Z>
class JSONSerdes: public SerdesTest<Z> {
public:
    const char* type() final;
    const char* serialize(const std::vector<Z>&) final;
    void deserialize(const char*) final;
    bool test(const std::vector<Z>&) final;

private:
    nlohmann::json _deserializedData;
};

And then here is a summary of the associated cpp file

#include "JSONSerdes.h"


template<typename T>
const char *JSONSerdes<T>::type() {
    ...
}

template<typename T>
const char *JSONSerdes<T>::serialize(const std::vector<T>& data) {
    ...
}

template<typename T>
void JSONSerdes<T>::deserialize(const char *serializedData) {
    ...
}

template<typename Z>
bool JSONSerdes<Z>::test(const std::vector<Z> &) {
    ...
}

And then the cmake executable line ...

add_executable(serdesPOC
        serdes/main.cpp
        serdes/serdes_test.h
        serdes/JSONSerdes.h
        serdes/JSONSerdes.cpp
        )

When I go to build i am getting this error

main.cpp.obj : error LNK2001: unresolved external symbol "public: virtual char const * __thiscall JSONSerdes<long>::type(void)" (?type@?$JSONSerdes@J@@UAEPBDXZ)
main.cpp.obj : error LNK2001: unresolved external symbol "public: virtual char const * __thiscall JSONSerdes<long>::serialize(class std::vector<long,class std::allocator<long> > const &)" (?serialize@?$JSONSerdes@J@@UAEPBDABV?$vector@JV?$allocator@J@std@@@std@@@Z)
main.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall JSONSerdes<long>::deserialize(char const *)" (?deserialize@?$JSONSerdes@J@@UAEXPBD@Z)
main.cpp.obj : error LNK2001: unresolved external symbol "public: virtual bool __thiscall JSONSerdes<long>::test(class std::vector<long,class std::allocator<long> > const &)" (?test@?$JSONSerdes@J@@UAE_NABV?$vector@JV?$allocator@J@std@@@std@@@Z)

I know it is a very similar problem to virtual function that is const in the base class and not const in the derived but i can not figure out what to change so I can keep my implementation of the methods in my cpp file and not the header.

Appreciate the help!

Tyler Weiss
  • 139
  • 1
  • 15
  • 2
    Does this answer your question? [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – dewaffled Sep 04 '21 at 16:48
  • Urg, yes. Realized this was an issue with templating and not with inheritance. I added the solution below, thank you – Tyler Weiss Sep 04 '21 at 16:58

1 Answers1

1

@dewaffled pointed me to my issue. It was not with how I was doing inheritance but with how I was defining the templated methods. I fixed it by renaming "JSONSerdes.cpp" to "JSONSerdes.tpp" (just to be semantically consistent) and then added the following line to the end of my header file

#include "JSONSerdes.tpp"

So the impl header ended up looking like ...

template<typename Z>
class JSONSerdes: public SerdesTest<Z> {
public:
    const char* type() final;
    const char* serialize(const std::vector<Z>&) final;
    void deserialize(const char*) final;
    bool test(const std::vector<Z>&) final;

private:
    nlohmann::json _deserializedData;
};

#include "JSONSerdes.tpp"
Tyler Weiss
  • 139
  • 1
  • 15