I am trying to implement a generic interface using the PIMPL idiom that requires some template member functions to provide functionality for ANY type. The issue is I can't find any way to support using template functions with the PIMPL idiom without pre-declaring every possible type that the function might use.
See related question: Pimpl Idiom with template member function
The accepted answer to that question suggests explicitly defining every type that will be used with the template. This is not always practical. Consider the following example:
example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
#include <memory>
class Example
{
public:
Example();
~Example();
// Generic template function in the interface
template <typename T>
void PrintData(const T& data) const;
private:
struct Impl;
std::unique_ptr<Impl> m_impl;
};
#endif
example.cpp
#include "example.h"
#include <iostream>
// Private implementation
struct Example::Impl
{
template <typename T>
void PrintData(const T& data) const
{
std::cout << data << std::endl;
}
};
// Note: using C++11 so "make_unique" is not available
Example::Example() : m_impl(new Impl()) {}
Example::~Example() = default;
// Forward the method call to the implementation
template <typename T>
void Example::PrintData(const T& data) const
{
m_impl->PrintData(data);
}
// Don't want to have to explicitly state all types...
// this is not practical because "PrintData" should work for ANY printable type.
// Uncommenting the line below will allow this example to compile,
// but it will only compile when used with "int" data.
//template void Example::PrintData(const int& data) const;
main.cpp
#include "example.h"
int main()
{
Example ex;
ex.PrintData(42);
}
Attempting to compile this will fail with an undefined reference error:
g++ -std=c++11 -o main main.cpp example.cpp
/tmp/cc6IhZsx.o: In function `main':
main.cpp:(.text+0x2b): undefined reference to `void Example::PrintData<int>(int const&) const'
collect2: error: ld returned 1 exit status
This example provides a very generic function in the interface that should work on ANY printable type. This poses an issue because we can't feasibly predict all types this function will be used on until compile-time.
How can I get a function like this to work with the PIMPL idiom (or some other method of creating a "compiler firewall")
Note that this example is intentionally trivial to demonstrate the problem. In the real world I have classes that contain MUCH more complicated template functions in the interface that need to work on many types. Because of this I have been unable to get these classes behind a compiler firewall like the PIMPL idiom provides.
I am open to considering alternatives to the PIMPL idiom that can achieve the desired effect if any such thing exists.