Reputation: 31
How can SDL types be used for smart pointers inside a wrapper class as members? (Using SDL2, mingw and gnu-make)
I know for me that question would not be straightforward, so here is the context as currently working:
main.cpp:
#include "WindowWrapper.h"
int main(int argnum, char* argv[])
{
//stuff...
WindowWrapper myWindow;
//more stuff...
}
WindowWrapper.h
//include guard...
class SDL_Window;
class WindowWrapper
{
public:
//constructor destructor, stuff....
private:
SDL_Window* window;
}
WindowWrapper.cpp
#include "WindowWrapper.h"
#include "SDL.h"
WindowWrapper::WindowWrapper()
{
int initResult = SDL_Init(SDL_INIT_VIDEO);
//error check, boring stuff...
window = SDL_CreateWindow(/* whatever, params... you know... */)
}
WindowWrapper::~WindowWrapper()
{
SDL_DestroyWindow(window);
window = nullptr;
SDL_Quit();
}
So as I said this is working fine, but I want to change the pointers like window (surface, renderer, texture, the usual) to smart pointers, like std::unique_ptr or similar.
But... Given a custom deleter like this:
struct CustomDeleter
{
void operator()(SDL_Window* window)
{
SDL_DestroyWindow(window);
}
void operator()(SDL_Window** window) //sounds crazy, but you would try even crazier stuff when experimenting
{
SDL_DestroyWindow(*window);
}
};
I failed with all the following (all is for WindowWrapper.h):
#incldue "SDL.h" //--> Fails to include in any header,
// causes the famous "Undefined Reference to WinMain" problem
/*
* Whatever definitions
*/
#include <memory>
typedef struct SDL_Window SDL_Window;
class WindowWrapper
{
/*
* Stuff
*/
private:
std::unique_ptr<SDL_Window, CustomDeleter> window; //--> obviously fails, incomplete type
}
#include <memory>
class SDL_Window;
class WindowWrapper
{
/*
* Stuff
*/
private:
std::unique_ptr<SDL_Window*, CustomDeleter> window; //--> acts like SDL_Window**...
//compiles, but almost impossible to get it work without extra intermediate objects, and other nasty hacks
}
I also tried to make a custom pointer template class that takes the SDL_Whatever* and the deleter function as construction parameters, and it was fine until I wanted to copy/move the wrapper objects (like storing them in a map or other container). At that point all the copy/move semantics got really messy, and implementing a reference counter like shared_ptr is way out of scope for me now, and anyways, that's why std smart pointers were implemented.
So to summarize:
Is there any way to include the SDL type itself in the header? I guess the reason of failure when SDL.h is included in the header is because unlike the cpp files, headers are not linked together during compilation, so it will never find the definition of the main function. But if just the type could be included (despite that they do not have their own include files in the SDL package -.-" ) that would solve this quite easily.
Is there a clean way to get around this "you may only declare raw pointers and references without the full type" rule for smart pointers? I know there is an exception for unique pointer if you can assure a bunch of stuff about the destructors, but I think a custom deleter defined like this is actually breaking those rules. But still I think smart pointers should have a way around this since they are actually pointers with extras. I just can't find how to do it.
Upvotes: 2
Views: 800
Reputation: 23701
You can get it to work just fine with your custom deleter: https://wandbox.org/permlink/K3L7BvJSf7OuKfFM
The key is that you declare the deleter operator()
in the header together with the wrapper, but implement its functionality in the associated .cpp
. That way it's a complete type, but you still encapsulate all the actual functionality in the wrapper .cpp
where you have access to actual SDL.
Upvotes: 1