-1

I'm trying to implement a templated reader class in g++ --std=c++17 that doesn't pull in all the various system headers for whatever stream-type I'm reading.

I can use the pimpl pattern to separate the template parameters from a base implementation, but I feel like I should be able avoid that by somehow specifying that the compilation unit's definition for that function won't change depending on the template parameter.

I can also use explicit specialization but defining every specialization is too onerous.

In the header:

template<typename Parser>
class FileStream
{
        Parser& parser;
        int fd;
        FileStream::FileStream(const char* filename, Parser& parser)
        : parser(parser)
        {
            init(filename);
        }

        void init(const char* filename);  // Preferably, implementation would go into .cpp file since this function does not use any template parameters

        void step(char* buf, size_t len)
        {
            // This function needs to be in the header because it uses parser
            parser.processMessage(buf, len);
        }
};

In the .cpp file:

// Let's try to not include these headers in the template definition header
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

template< /* ??? */ >
void FileStream::init(const char* filename)
{
    // Note: No template parameters are used in this function
    fd = open(filename, O_RDONLY);
}
occor
  • 1
  • 2
  • 1
    You could inherit from a class that has this function and member. – wally Jan 08 '19 at 20:04
  • 1
    I disagree with the linked duplicate. It may be related, but this is asking if there is a way around having to include the definition in the header, not why it's necessary to define the member functions in the header. – François Andrieux Jan 08 '19 at 20:08

1 Answers1

1

The comment by wally already has the answer. Just move everything that does not depend on the template parameter into a base class. Once you have to specialize the template this is a good idea anyhow.

In the header:

struct foo_base { 
    void init(const char* filename);
};

template <typename T> 
struct foo : foo_base { /*...*/ };

// ... implement methods that depend on the template parameter

In the source:

#include <foo.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void foo_base::init(const char* filename) { /*...*/ }
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185