Идиома PImpl с использованием std :: unique_pointer с классом реализации в отдельном исходном файле - PullRequest
0 голосов
/ 27 апреля 2020

Я пишу простую библиотеку для обработки окон на разных платформах. Чтобы абстрагировать код, определяющий платформу c, я хочу использовать идиому PImpl с std :: unique_ptr и предоставить частную реализацию спецификации платформы c с фабричной функцией. Вот что у меня сейчас:

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>();
}

Это, кажется, делает то, что я хочу , Моя проблема заключается в том, что в настоящее время я должен указать " Window :: " перед всем, что есть в WindowImpl. cpp. Поскольку Window является классом, а не пространством имен, «использование Window» не работает. Все примеры, которые я нашел об этой топике c, имеют полное определение класса Impl внутри исходного файла своего класса, используя его, и поэтому не имеют этой проблемы. Но мне нужно иметь WindowImpl в отдельном заголовке, если я хочу извлечь из него реализации платформы c.

Есть ли способ сохранить WindowImpl в своем собственном заголовочном / исходном файле и избавиться от него? многословие?

1 Ответ

1 голос
/ 27 апреля 2020

Вы можете использовать псевдоним типа, однако для этого потребуется, чтобы вложенный класс был опубликован c, что может отразить использование идиомы PImpl:

using WImpl = typename Window::WindowImpl;

std::unique_ptr<WImpl> WImpl::create(){
    //implementation goes here
}

Редактировать:

Кроме этого, вам, возможно, придется использовать макросы для удаления многословия:

#define WIMPL Window::WindowImpl;

std::unique_ptr<WIMPL> WIMPL::create(){
    //implementation goes here
}
...