C++11 - Problem with pimpl-idiom?

Hi, folks!

I guess I have ran into problem with pimpl-idiom, since I can't figure out what else could be possibly wrong.

My code currently has problems with undefined references. There shouldn't be any other compilations errors, at least I didn't get any other of them. Here's my code:

PointerSmartSafe.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/// ----------------------------
/// @author		God
/// @project	Helixirr Widgets
/// ----------------------------
#ifndef __HELIXIRRWIDGETS_HEADER_POINTERSMARTSAFE__
#define __HELIXIRRWIDGETS_HEADER_POINTERSMARTSAFE__
#include <memory>
namespace HelixirrWidgets{
	/// --------------------------------------------------
	/// @class	PointerSmartSafe
	/// @brief	Represents a smart pointer, which is both
	/// 		copy- and move-assignable.
	/// @note	There are less explicit constructors to
	/// 		be found compared to the unique_ptr-class.
	/// --------------------------------------------------
	template<typename T, class Deleter = std::default_delete<T>>
	class PointerSmartSafe{
	public:

		/// Constructors & destructors:
		PointerSmartSafe(PointerSmartSafe const& pointer_smart_safe_);
		PointerSmartSafe(PointerSmartSafe&& pointer_smart_safe_) = default;
		PointerSmartSafe(T* pointer_ = nullptr) noexcept;

		/// Member functions:
		inline T* get(void) const noexcept;
		inline Deleter& get_deleter(void) noexcept;
		inline Deleter const& get_deleter(void) const noexcept;
		inline void release(void) noexcept;
		inline void reset(T* pointer_) noexcept;
		inline void swap(PointerSmartSafe& pointer_smart_safe_) noexcept;

		/// Member functions (overloaded operators):
		inline PointerSmartSafe& operator=(PointerSmartSafe const& pointer_smart_safe_);
		inline PointerSmartSafe& operator=(PointerSmartSafe&& pointer_smart_safe_) = default;

		/// Member functions (overloaded operators, pointer):
		T& operator*(void) const noexcept;
		T* operator->(void) const noexcept;

		/// Member functions (overloaded operators, typecast):
		explicit inline operator bool(void) const noexcept;

	private:
		/// Member data:
		std::unique_ptr<T> _m_opPointerUnique;
	};
#include <helixirrwidgets/PointerSmartSafe.hpp>
}
#endif /** __HELIXIRRWIDGETS_HEADER_POINTERSMARTSAFE__ **/ 


PointerSmartSafe.inl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/// ----------------------------
/// @author		God
/// @project	Helixirr Widgets
/// ----------------------------

/// --------------------------------------------------
/// @class	PointerSmartSafe
/// @brief	Represents a smart pointer, which is both
/// 		copy- and move-assignable.
/// @note	There are less explicit constructors to
/// 		be found compared to the unique_ptr-class.
/// --------------------------------------------------
/// Constructors & destructors:
template<typename T>
PointerSmartSafe<T>::PointerSmartSafe(PointerSmartSafe const& pointer_smart_safe_) : _m_opPointerUnique(decltype(_m_opPointerUnique)(new T(*_m_opPointerUnique.get()))){

}
template<typename T>
PointerSmartSafe<T>::PointerSmartSafe(T* pointer_) noexcept : _m_opPointerUnique(decltype(_m_opPointerUnique)(pointer_)){

}

/// Member functions:
template<typename T>
T* PointerSmartSafe<T>::get(void) const noexcept{
	return _m_opPointerUnique.get();
}
template<typename T>
Deleter& PointerSmartSafe<T>::get_deleter(void) noexcept{
	return _m_opPointerUnique.get_deleter();
}
template<typename T>
Deleter const& PointerSmartSafe<T>::get_deleter(void) const noexcept{
	return _m_opPointerUnique.get_deleter();
}
template<typename T>
void PointerSmartSafe<T>::release(void) noexcept{
	_m_opPointerUnique.release();
}
template<typename T>
void PointerSmartSafe<T>::reset(T* pointer_) noexcept{
	_m_opPointerUnique.reset(pointer_);
}
template<typename T>
void PointerSmartSafe<T>::swap(PointerSmartSafe& pointer_smart_safe_) noexcept{
	_m_opPointerUnique.swap(pointer_smart_safe_);
}
/// Member functions (overloaded operators):
template<typename T>
PointerSmartSafe<T>& PointerSmartSafe<T>::operator=(PointerSmartSafe const& pointer_smart_safe_){
	_m_opPointerUnique = decltype(_m_opPointerUnique)(new T(*_m_opPointerUnique.get()));
	return *this;
}
/// Member functions (overloaded operators, pointer):
template<typename T>
T& PointerSmartSafe<T>::operator*(void) const noexcept{
	return _m_opPointerUnique.operator*();
}
template<typename T>
T* PointerSmartSafe<T>::operator->(void) const noexcept{
	return _m_opPointerUnique.operator->();
}
/// Member functions (overloaded operators, typecast):
template<typename T>
PointerSmartSafe<T>::operator bool(void) const noexcept{
	return _m_opPointerUnique.operator bool();
}


Window.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/// ----------------------------
/// @author		God
/// @project	Helixirr Widgets
/// ----------------------------
#ifndef __HELIXIRRWIDGETS_HEADER_WINDOW__
#define __HELIXIRRWIDGETS_HEADER_WINDOW__
#include <array>
#include <string>
#include <helixirrwidgets/PointerSmartSafe.hpp>
namespace HelixirrWidgets{
	/// ----------------------------
	/// @class	Window
	/// @brief	Represents a window.
	/// ----------------------------
	class Window{
	public:

		/// Constructors & destructors:
		Window(void);
		Window(Window const& window_);
		Window(Window&& window_);
		explicit Window(std::string const& name_);
		explicit Window(std::string&& name_);
		~Window(void);

		/// Member functions:
		inline std::string const& name(void) const;
		Window& name(std::string const& name_);
		Window& name(std::string&& name_);
		inline std::array<unsigned int, 2> const& position(void) const;
		Window& position(std::array<unsigned int, 2> const& position_);
		Window& position(std::array<unsigned int, 2>&& position_);
		Window& position(unsigned int const& x_, unsigned int const& y_);
		Window& position(unsigned int&& x_, unsigned int&& y_);
		Window& save_changes(void);
		inline std::array<unsigned int, 2> const& size(void) const;
		Window& size(std::array<unsigned int, 2> const& size_);
		Window& size(std::array<unsigned int, 2>&& size_);
		Window& size(unsigned int const& width_, unsigned int const& height_);
		Window& size(unsigned int&& width_, unsigned int&& height_);
		inline bool const& visible(void) const;
		Window& visible(bool const& visible_);
		Window& visible(bool&& visible_);

		/// Member functions (overloaded operators, assignment):
		Window& operator=(Window const& window_) = default;
		Window& operator=(Window&& window_) = default;

	private:
		/// Inner classes:
		class Helper;
		/// Member data:
		bool _m_bVisible;
		PointerSmartSafe<Window::Helper> _m_opHelper;
		std::array<unsigned int, 2> _m_uiPos, _m_uiSize;
		std::string _m_oName;
	};
#include <helixirrwidgets/Window.inl>
}
#endif /** __HELIXIRRWIDGETS_HEADER_WINDOW__ **/ 


Window.inl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/// ----------------------------
/// @author		God
/// @project	Helixirr Widgets
/// ----------------------------

/// ----------------------------
/// @class	Window
/// @brief	Represents a window.
/// ----------------------------
/// Member functions:
std::string const& Window::name(void) const{
	return _m_oName;
}
std::array<unsigned int, 2> const& Window::position(void) const{
	return _m_uiPos;
}
std::array<unsigned int, 2> const& Window::size(void) const{
	return _m_uiSize;
}
bool const& Window::visible(void) const{
	return _m_bVisible;
}

Last edited on
And yes, it goes on.

Window.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/// ----------------------------
/// @author		God
/// @project	Helixirr Widgets
/// @note		Windows only
/// ----------------------------
#include <helixirrwidgets/Window.hpp>
using namespace HelixirrWidgets;

/// ----------------------------
/// @class	Window
/// @brief	Represents a window.
/// ----------------------------
/// Member functions:
Window& Window::name(std::string const& name_){
	_m_oName = name_;
	return *this;
}
Window& Window::name(std::string&& name_){
	_m_oName = std::move(name_);
	return *this;
}
Window& Window::position(std::array<unsigned int, 2> const& position_){
	_m_uiPos = position_;
	return *this;
}
Window& Window::position(std::array<unsigned int, 2>&& position_){
	_m_uiPos = std::move(position_);
	return *this;
}
Window& Window::position(unsigned int const& x_, unsigned int const& y_){
	_m_uiPos[0] = x_;
	_m_uiPos[1] = y_;
	return *this;
}
Window& Window::position(unsigned int&& x_, unsigned int&& y_){
	_m_uiPos[0] = std::move(x_);
	_m_uiPos[1] = std::move(y_);
	return *this;
}
Window& Window::size(std::array<unsigned int, 2> const& size_){
	_m_uiSize = size_;
	return *this;
}
Window& Window::size(std::array<unsigned int, 2>&& size_){
	_m_uiSize = std::move(size_);
	return *this;
}
Window& Window::size(unsigned int const& width_, unsigned int const& height_){
	_m_uiSize[0] = width_;
	_m_uiSize[1] = height_;
	return *this;
}
Window& Window::size(unsigned int&& width_, unsigned int&& height_){
	_m_uiSize[0] = std::move(width_);
	_m_uiSize[1] = std::move(height_);
	return *this;
}
Window& Window::visible(bool const& visible_){
	_m_bVisible = visible_;
	return *this;
}
Window& Window::visible(bool&& visible_){
	_m_bVisible = std::move(visible_);
	return *this;
}


Window-windows.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/// ----------------------------
/// @author		God
/// @project	Helixirr Widgets
/// @note		Windows only
/// ----------------------------
#include <windows.h>
#include <helixirrwidgets/Window.hpp>
using namespace HelixirrWidgets;

/// ----------------------------
/// @class	Window
/// @brief	Represents a window.
/// ----------------------------
/// Inner classes:
class Window::Helper{
public:

	/// Constructors & destructors:
	Helper(void) : created_window(false), registered_class_window(false), handle_instance(GetModuleHandle(NULL)), handle_window(nullptr), name_class_window(Window::Helper::_generate_name_class_window()){

	}
	Helper(Helper const& helper_) : created_window(false), registered_class_window(false), handle_instance(helper_.handle_instance), handle_window(helper_.handle_window), name_class_window(Window::Helper::_generate_name_class_window()), class_window(helper_.class_window){

	}
	Helper(Helper&& helper_) : created_window(false), registered_class_window(false), handle_instance(std::move(helper_.handle_instance)), handle_window(std::move(helper_.handle_window)), name_class_window(helper_.name_class_window), class_window(std::move(helper_.class_window)){
		helper_.handle_instance = nullptr;
		helper_.handle_window = nullptr;
	}
	~Helper(void){
		handle_instance = nullptr;
		handle_window = nullptr;
	}

	/// Member data:
	bool mutable created_window, registered_class_window;
	HINSTANCE mutable handle_instance;
	HWND mutable handle_window;
	std::string mutable name_class_window;
	WNDCLASSEX mutable class_window;

	/// Member functions (overloaded operators, assignment):
	Helper& operator=(Helper const& helper_){
		class_window = helper_.class_window;
		created_window = false;
		handle_instance = helper_.handle_instance;
		handle_window = helper_.handle_window;
		name_class_window = helper_.name_class_window;
		registered_class_window = false;
		return *this;
	}
	Helper& operator=(Helper&& helper_){
		class_window = std::move(helper_.class_window);
		created_window = false;
		handle_instance = std::move(helper_.handle_instance);
		handle_window = std::move(helper_.handle_window);
		name_class_window = std::move(helper_.name_class_window);
		registered_class_window = false;
		return *this;
	}

	/// Static member functions:
	static inline LRESULT CALLBACK handle_callback(HWND handle_window_, UINT message_, WPARAM wparam_, LPARAM lparam_){
		return DefWindowProc(handle_window_, message_, wparam_, lparam_);
	}

private:
	/// Static member functions:
	static char const* _generate_name_class_window(void){
		static unsigned long long __counter = 125;

		auto const __result = __counter % 125;
		bool const __exists_remainder = __result;

		++__counter;

		std::string __name_class_window;
		__name_class_window.assign(__result - __exists_remainder, 125);
		__name_class_window += static_cast<char>(__result);

		return __name_class_window.c_str();
	}

};
/// Constructors & destructors:
Window::Window(void) : _m_opHelper(){

}
Window::Window(Window const& window_) = default;
Window::Window(Window&& window_) = default;
Window::Window(std::string const& name_) : _m_bVisible(false), _m_oName(name_){

}
Window::Window(std::string&& name_) : _m_bVisible(false), _m_oName(std::move(name_)){

}
Window::~Window(void) = default;
/// Member functions:
Window& Window::save_changes(void){ /* UNFINISHED! */
	// If window class hasn't been created and registered yet:
	if(_m_opHelper->registered_class_window){
		// Create and register window class:
		_m_opHelper->registered_class_window = true;
		_m_opHelper->class_window = WNDCLASSEX{
			sizeof(WNDCLASSEX),
			CS_HREDRAW | CS_VREDRAW,
			Window::Helper::handle_callback,
			0, 0,
			_m_opHelper->handle_instance,
			LoadIcon(_m_opHelper->handle_instance, NULL),
			LoadCursor(NULL, IDC_ARROW),
			reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)),
			NULL,
			_m_opHelper->name_class_window.c_str(),
			LoadIcon(_m_opHelper->handle_instance, NULL)
		};
		RegisterClassEx(&_m_opHelper->class_window);
	}

	// If window hasn't been created yet:
	if(_m_opHelper->created_window){
		_m_opHelper->created_window = true;
		_m_opHelper->handle_window = CreateWindow(
			_m_opHelper->name_class_window.c_str(),
			_m_oName.c_str(),
			WS_VISIBLE,
			_m_uiPos[0], _m_uiPos[1],
			_m_uiSize[0], _m_uiSize[1],
			NULL, NULL, _m_opHelper->handle_instance, NULL
		);
	}
	return *this;
}


HelixirrWidgets.hpp
1
2
3
4
5
6
7
8
9
/// ----------------------------
/// @author		God
/// @project	Helixirr Widgets
/// ----------------------------
#ifndef __HELIXIRRWIDGETS_HEADER_HELIXIRRWIDGETS__
#define __HELIXIRRWIDGETS_HEADER_HELIXIRRWIDGETS__
#include <helixirrwidgets/PointerSmartSafe.hpp>
#include <helixirrwidgets/Window.hpp>
#endif /** __HELIXIRRWIDGETS_HEADER_HELIXIRRWIDGETS__ **/ 


main.cpp
1
2
3
4
5
6
7
8
9
10
/// ----------------------------
/// @author		God
/// @project	Helixirr Widgets
/// ----------------------------
#include <helixirrwidgets/HelixirrWidgets.hpp>

int main(void){
    HelixirrWidgets::Window __window_game("Sample Program");
    return 0;
}


God shall help me now through other people. Thank you.
Last edited on
Topic archived. No new replies allowed.