1

When compiling my code (you will see why this big and not an MRE snippet later)

    template<typename Elem>
    class base_stream
    {
    protected:
        array_list<Elem>* buffer_ = nullptr; // array_list is my class, it works
    public:
        virtual void open() = 0;
        virtual void close() = 0;
    };
    template<typename Elem>
    class base_input_stream : public base_stream<Elem>
    {
    public:
        void open() override
        {
            this->buffer_ = new array_list<Elem>;           
        }
        void close() override
        {
            this->buffer_ = nullptr;
        }
        Elem* read_until(Elem terminator)
        {
            Elem e;
            while((e = read()) != terminator) this->buffer_->add(e);
            return this->buffer_->as_array();
        }
        virtual Elem read();
    };
    class input_stream : public base_input_stream<char>
    {
    private:
        FILE* file_;
    public:
        input_stream(FILE* f)
        {
            file(f);
            open();
        }
        input_stream() { open(); }
        ~input_stream()
        {
            close();
            delete buffer_;
        }
        char* read_line()
        {
            return this->read_until('\n');
            // the problem is here, when I remove read_line, everything works.
        }
        char read() override
        {
            return fgetc(file_);
        }

        void file(FILE* f)
        {
            file_ = f;
        }  
};

and the cpp file

msl::input_stream is(stdin);
msl::stdos.write("Hello, ");
msl::stdos.write(is.read_line());

(please don't judge me for what I'm doing...)

this error appears:

Undefined symbols for architecture x86_64:
  "msl::base_input_stream<char>::read()", referenced from:
      vtable for msl::base_input_stream<char> in msl-test-9638bd.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

but (strangely) this works:

#include <iostream>

template<typename E>
class X
{

};

template<typename E>
class Y : public X<E>
{
public:
    void doStuff(E foo)
    {
        std::cout << foo << std::endl;
    }
};

class Z : public Y<char>
{
public:
    void hmm() {
        doStuff('h');
        // or Y<char>::doStuff('h');
        // or this->doStuff('h');
    }
};

Z hmm = Z();

and compiles without any errors. (the output is as expected h)

What is the problem here. The error is strange because other methods work and only read_line doesn't

somerandomdev49
  • 177
  • 1
  • 3
  • 11
  • 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) – super Mar 18 '20 at 07:56
  • No, it doesn't I tried moving `read_line` implementation to the global scope and making it inline, but the error doesn't change at all. And I don't have .cpp files for implementations, I want everything to be in one header file. – somerandomdev49 Mar 18 '20 at 07:58
  • 3
    There is no implementation for `virtual Elem read();`, which your error message is complaining about. – super Mar 18 '20 at 08:00
  • 3
    Make `read` pure virtual `virtual Elem read() = 0;` – Timo Mar 18 '20 at 08:00
  • Thank you! It works! sorry for the dumb question. – somerandomdev49 Mar 18 '20 at 08:03

0 Answers0