Update example to use type erased polymorphism technique
This commit is contained in:
@@ -26,6 +26,8 @@ add_executable(
|
|||||||
${SOURCE_FILES}
|
${SOURCE_FILES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_include_directories(${current_target} PRIVATE .)
|
||||||
|
|
||||||
if( ENABLE_ALL_REASONABLE_WARNINGS )
|
if( ENABLE_ALL_REASONABLE_WARNINGS )
|
||||||
MESSAGE("-- Additional Warnings Enabled")
|
MESSAGE("-- Additional Warnings Enabled")
|
||||||
target_enable_warnings(${current_target})
|
target_enable_warnings(${current_target})
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ auto main() -> int
|
|||||||
.name = "Starter Window"
|
.name = "Starter Window"
|
||||||
});
|
});
|
||||||
|
|
||||||
while (!window->ShouldClose())
|
while (!ShouldClose(window))
|
||||||
{
|
{
|
||||||
window->PumpMessages();
|
PumpMessages(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,19 @@
|
|||||||
#include "../window.h"
|
#include "window.h"
|
||||||
|
|
||||||
namespace starter_window
|
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
|
void PumpMessages(NullWindowImpl&)
|
||||||
|
|
||||||
std::unique_ptr<starter_window::Window> swCreateWindow(starter_window::WindowCreateParams)
|
|
||||||
{
|
{
|
||||||
auto result = std::make_unique<starter_window::NullWindowImpl>();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShouldClose(const NullWindowImpl&)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace starter_window
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "../window.h"
|
#include "window.h"
|
||||||
|
|
||||||
#ifndef NOMINMAX
|
#ifndef NOMINMAX
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
@@ -35,34 +35,43 @@ static LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM wParam, LPA
|
|||||||
namespace starter_window
|
namespace starter_window
|
||||||
{
|
{
|
||||||
|
|
||||||
class Win32WindowImpl final : public Window
|
struct Win32WindowImpl final
|
||||||
{
|
{
|
||||||
public:
|
HINSTANCE m_hInstance;
|
||||||
Win32WindowImpl();
|
HWND m_hWnd;
|
||||||
~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;
|
|
||||||
bool m_close;
|
bool m_close;
|
||||||
};
|
};
|
||||||
|
|
||||||
Win32WindowImpl::Win32WindowImpl()
|
void PumpMessages(Win32WindowImpl& window)
|
||||||
: hInstance(GetModuleHandle(NULL))
|
|
||||||
, hWnd(nullptr)
|
|
||||||
, m_close(false)
|
|
||||||
{
|
{
|
||||||
|
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";
|
const char className[] = "Win32WindowImpl";
|
||||||
|
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||||
|
starter_window::Win32WindowImpl result = {
|
||||||
|
.m_hInstance = nullptr,
|
||||||
|
.m_hWnd = nullptr,
|
||||||
|
.m_close = true
|
||||||
|
};
|
||||||
|
|
||||||
WNDCLASSEX wc = {};
|
WNDCLASSEX wc = {};
|
||||||
|
|
||||||
@@ -75,7 +84,7 @@ bool Win32WindowImpl::init(WindowCreateParams params)
|
|||||||
if (RegisterClassEx(&wc) == 0)
|
if (RegisterClassEx(&wc) == 0)
|
||||||
{
|
{
|
||||||
MessageBox(nullptr, "Call to RegisterClass failed", "Fatal Error", MB_OK);
|
MessageBox(nullptr, "Call to RegisterClass failed", "Fatal Error", MB_OK);
|
||||||
return false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND window = CreateWindowEx(
|
HWND window = CreateWindowEx(
|
||||||
@@ -92,41 +101,14 @@ bool Win32WindowImpl::init(WindowCreateParams params)
|
|||||||
if (window == nullptr)
|
if (window == nullptr)
|
||||||
{
|
{
|
||||||
MessageBox(nullptr, "Call to CreateWindow failed", "Fatal Error", MB_OK);
|
MessageBox(nullptr, "Call to CreateWindow failed", "Fatal Error", MB_OK);
|
||||||
return false;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowWindow(window, SW_SHOW);
|
ShowWindow(window, SW_SHOW);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Win32WindowImpl::PumpMessages()
|
result.m_hInstance = hInstance;
|
||||||
{
|
result.m_hWnd = window;
|
||||||
MSG message = {};
|
result.m_close = false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
39
src/window.h
39
src/window.h
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace starter_window
|
namespace starter_window
|
||||||
{
|
{
|
||||||
@@ -17,11 +18,41 @@ struct WindowCreateParams
|
|||||||
class Window
|
class Window
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Window() = default;
|
template<typename T>
|
||||||
virtual void PumpMessages() = 0;
|
Window(T t)
|
||||||
virtual bool ShouldClose() = 0;
|
: 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);
|
||||||
|
|||||||
Reference in New Issue
Block a user