is there any way to properly implement the PIMPL idiom with a template class in C++?
For example, I have the following PIMPL class:
template <typename T> struct PrivateImplementation {
PrivateImplementation<T>(T* impl) : implementation(impl) {
}
~PrivateImplementation<T>() {
if (implementation != nullptr) delete implementation;
}
PrivateImplementation<T>(const PrivateImplementation<T>& c) = delete;
void operator=(const PrivateImplementation<T>& a) = delete;
PrivateImplementation<T>(PrivateImplementation<T>&& m) {
implementation = m.implementation;
m.implementation = nullptr;
}
T* operator->() const {
return implementation;
}
private:
T* implementation;
};
However, when I use it like below, the compiler complains (a warning) that I'm deleting an incomplete type:
Logger.h
class LoggerStream {
public:
LoggerStream(std::wstring componentName);
~LoggerStream();
LoggerStream(const LoggerStream&) = delete;
void operator=(const LoggerStream&) = delete;
LoggerStream(LoggerStream&&);
void Write(std::wstring message, const char* __function__, const char* __file__, int __line__) const;
void Write(std::wstring message) const;
private:
struct LoggerStreamImpl;
PrivateImplementation<LoggerStreamImpl> impl;
};
Logger.cpp
struct LoggerStream::LoggerStreamImpl {
LoggerStreamImpl(std::wstring componentName) : componentName(componentName) { }
~LoggerStreamImpl() = default;
LoggerStreamImpl(const LoggerStreamImpl&) = delete;
void operator=(const LoggerStreamImpl&) = delete;
LoggerStreamImpl(LoggerStreamImpl&&);
const std::wstring componentName;
};
LoggerStream::LoggerStream(std::wstring componentName)
: impl(new LoggerStreamImpl { componentName }) { }
LoggerStream::~LoggerStream() { }
void LoggerStream::Write(std::wstring message, const char* __function__, const char* __file__, int __line__) const {
// Some implementation
}
void LoggerStream::Write(std::wstring message) const {
// Some implementation
}
I clearly have a defined destructor for LoggerStreamImpl
right there in the .cpp, so what gives?
Thank you.