Update example to use type erased polymorphism technique

This commit is contained in:
McMassiveNZ
2023-06-29 22:50:21 +02:00
parent 9bcbe577a9
commit 4a17314eaa
5 changed files with 83 additions and 77 deletions

View File

@@ -26,6 +26,8 @@ add_executable(
${SOURCE_FILES}
)
target_include_directories(${current_target} PRIVATE .)
if( ENABLE_ALL_REASONABLE_WARNINGS )
MESSAGE("-- Additional Warnings Enabled")
target_enable_warnings(${current_target})

View File

@@ -12,9 +12,9 @@ auto main() -> int
.name = "Starter Window"
});
while (!window->ShouldClose())
while (!ShouldClose(window))
{
window->PumpMessages();
PumpMessages(window);
}
}

View File

@@ -1,28 +1,19 @@
#include "../window.h"
#include "window.h"
namespace starter_window
{
class NullWindowImpl final : public Window
struct NullWindowImpl
{
public:
NullWindowImpl() = default;
~NullWindowImpl() override = default;
NullWindowImpl(NullWindowImpl&&) = delete;
NullWindowImpl& operator=(NullWindowImpl&&) = delete;
NullWindowImpl(const NullWindowImpl&) = delete;
NullWindowImpl& operator=(const NullWindowImpl&) = delete;
void PumpMessages() override {}
bool ShouldClose() override { return false; }
};
} // namespace starter_window
std::unique_ptr<starter_window::Window> swCreateWindow(starter_window::WindowCreateParams)
void PumpMessages(NullWindowImpl&)
{
auto result = std::make_unique<starter_window::NullWindowImpl>();
return result;
}
bool ShouldClose(const NullWindowImpl&)
{
return true;
}
} // namespace starter_window

View File

@@ -1,4 +1,4 @@
#include "../window.h"
#include "window.h"
#ifndef NOMINMAX
#define NOMINMAX
@@ -35,34 +35,43 @@ static LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM wParam, LPA
namespace starter_window
{
class Win32WindowImpl final : public Window
struct Win32WindowImpl final
{
public:
Win32WindowImpl();
~Win32WindowImpl() override = default;
Win32WindowImpl(const Win32WindowImpl&) = delete;
Win32WindowImpl& operator=(const Win32WindowImpl&) = delete;
bool init(WindowCreateParams params);
void PumpMessages() override;
bool ShouldClose() override;
HINSTANCE hInstance;
HWND hWnd;
HINSTANCE m_hInstance;
HWND m_hWnd;
bool m_close;
};
Win32WindowImpl::Win32WindowImpl()
: hInstance(GetModuleHandle(NULL))
, hWnd(nullptr)
, m_close(false)
void PumpMessages(Win32WindowImpl& window)
{
MSG message = {};
if (GetMessage(&message, NULL, 0, 0) != 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
else
{
// GetMessage returned WM_QUIT
window.m_close = true;
}
}
bool Win32WindowImpl::init(WindowCreateParams params)
bool ShouldClose(const Win32WindowImpl& window)
{
return window.m_close;
}
} // namespace starter_window
starter_window::Window swCreateWindow(starter_window::WindowCreateParams params)
{
const char className[] = "Win32WindowImpl";
HINSTANCE hInstance = GetModuleHandle(NULL);
starter_window::Win32WindowImpl result = {
.m_hInstance = nullptr,
.m_hWnd = nullptr,
.m_close = true
};
WNDCLASSEX wc = {};
@@ -75,7 +84,7 @@ bool Win32WindowImpl::init(WindowCreateParams params)
if (RegisterClassEx(&wc) == 0)
{
MessageBox(nullptr, "Call to RegisterClass failed", "Fatal Error", MB_OK);
return false;
return result;
}
HWND window = CreateWindowEx(
@@ -92,41 +101,14 @@ bool Win32WindowImpl::init(WindowCreateParams params)
if (window == nullptr)
{
MessageBox(nullptr, "Call to CreateWindow failed", "Fatal Error", MB_OK);
return false;
return result;
}
ShowWindow(window, SW_SHOW);
return true;
}
void Win32WindowImpl::PumpMessages()
{
MSG message = {};
if (GetMessage(&message, NULL, 0, 0) != 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
else
{
// GetMessage returned WM_QUIT
m_close = true;
}
}
bool Win32WindowImpl::ShouldClose()
{
return m_close;
}
} // namespace starter_window
std::unique_ptr<starter_window::Window> swCreateWindow(starter_window::WindowCreateParams params)
{
auto result = std::make_unique<starter_window::Win32WindowImpl>();
if (result->init(params) == false)
{
result = nullptr;
}
result.m_hInstance = hInstance;
result.m_hWnd = window;
result.m_close = false;
return result;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <memory>
#include <optional>
namespace starter_window
{
@@ -17,11 +18,41 @@ struct WindowCreateParams
class Window
{
public:
virtual ~Window() = default;
virtual void PumpMessages() = 0;
virtual bool ShouldClose() = 0;
template<typename T>
Window(T t)
: self{std::make_unique<model_t<T>>(std::move(t))}
{
}
~Window() = default;
Window(Window&&) = default;
Window& operator=(Window&&) = default;
Window(const Window&) = delete;
Window operator=(const Window&) = delete;
friend void PumpMessages(Window& window) { window.self->PumpMessages_(); }
friend bool ShouldClose(const Window& window) { return window.self->ShouldClose_(); }
private:
struct concept_t
{
virtual ~concept_t() = default;
virtual void PumpMessages_() = 0;
virtual bool ShouldClose_() const = 0;
};
template<typename T>
struct model_t final : concept_t
{
model_t(T&& data) : m_data(std::move(data)) {}
virtual void PumpMessages_() override{ PumpMessages(m_data); }
virtual bool ShouldClose_() const override { return ShouldClose(m_data); }
T m_data;
};
std::unique_ptr<concept_t> self;
};
}
std::unique_ptr<starter_window::Window> swCreateWindow(starter_window::WindowCreateParams params);
starter_window::Window swCreateWindow(starter_window::WindowCreateParams params);