I am writing a simple library to handle window creation across different platforms. To abstract away the platform specific code i want to use the PImpl idiom with a std::unique_ptr and provide a platform specific private implementation with a factory function. This is what i currently have:
Window.h:
#pragma once
#include <memory>
class Window
{
public:
Window();
~Window();
private:
class WindowImpl;
std::unique_ptr<WindowImpl> impl;
};
Window.cpp:
#include "Window.h"
#include "WindowImpl.h"
Window::Window() : impl(WindowImpl::create()) {}
Window::~Window() = default;
WindowImpl.h:
#include "Window.h"
#include <memory>
class Window::WindowImpl
{
public:
static std::unique_ptr<WindowImpl> create();
};
WindowImpl.cpp:
#include "WindowImpl.h"
std::unique_ptr<Window::WindowImpl> Window::WindowImpl::create()
{
// the plan is to return the platform specific WindowImpl implementation here
return std::make_unique<Window::WindowImpl>();
}
This seems to do what i want. My Problem ist that i currently have to specify "Window::" in front of basicly everything in WindowImpl.cpp. Since Window is a class and not a namespace "using Window" doesn't work. The examples i found about this topic all have their full Impl class definition inside the source file of their class using it and thus didn't have this problem. But i need to have WindowImpl in a seperate header if i want to derive the platform specific implemetations from it.
Is there a way to keep WindowImpl in its own header/source file and get rid of that verbosity?
You could use type-aliasing, however, that will require you to make the nested class public, which may defeat the use of the PImpl idiom:
using WImpl = typename Window::WindowImpl;
std::unique_ptr<WImpl> WImpl::create(){
//implementation goes here
}
Edit:
Other than that, you may have to use macros to remove the verbosity:
#define WIMPL Window::WindowImpl;
std::unique_ptr<WIMPL> WIMPL::create(){
//implementation goes here
}