Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
SC::OpaqueObject< Definition > Struct Template Reference

Hides implementation details from public headers (static PIMPL). More...

#include <OpaqueObject.h>

Public Types

using Object = typename Definition::Object
 

Public Member Functions

 OpaqueObject (OpaqueObject &&other)
 
OpaqueObjectoperator= (OpaqueObject &&other)
 
 OpaqueObject (const OpaqueObject &)=delete
 
OpaqueObjectoperator= (const OpaqueObject &)=delete
 
Object & get ()
 
const Object & get () const
 

Detailed Description

template<typename Definition>
struct SC::OpaqueObject< Definition >

Hides implementation details from public headers (static PIMPL).


Opaque object avoids the heap allocation that often comes with PIMPL, allowing to hide OS specific details from public headers. User declares size in bytes of a struct in the header but the structure can be defined in an implementation .cpp file. Choosing a size that is too small will generate a static_assert that contains in the error message the minimum size to use. Up to 4 functions will need to be defined to avoid linker errors (construct, destruct, moveConstruct, moveAssign). These functions are meant to be defined in a .cpp file that will know how to construct Object, as it can see its definition.

Template Parameters
DefinitionPass in a custom Definition declaring Sizes and alignment on different platforms

Example:

... in the header file

struct FileSystemWatcher
{
private:
struct Internal;
struct InternalDefinition
{
static constexpr int Windows = 3 * sizeof(void*);
static constexpr int Apple = 43 * sizeof(void*) + sizeof(Mutex);
static constexpr int Linux = sizeof(void*) * 4;
static constexpr int Default = Linux;
static constexpr size_t Alignment = alignof(void*);
using Object = Internal;
};
public:
// Must be public to avoid GCC complaining
using InternalOpaque = OpaqueObject<InternalDefinition>;
private:
InternalOpaque internal;
//...

... in .cpp file Declare Internal struct with all platform specific details (requiring OS specific headers).

#include "../../FileSystemWatcher/FileSystemWatcher.h"
#include "../../Foundation/Deferred.h"
#include "../../Threading/Atomic.h"
#include "../../Threading/Threading.h"
#include <CoreServices/CoreServices.h> // FSEvents
#include <AvailabilityMacros.h>
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE
// TODO: Figure out another API for ios as this is a private API and it will not be accepted on app store.
#include "FSEventsIOS.h"
#endif
struct SC::FileSystemWatcher::Internal
{
FileSystemWatcher* self = nullptr;
CFRunLoopRef runLoop = nullptr;
CFRunLoopSourceRef refreshSignal = nullptr;
FSEventStreamRef fsEventStream = nullptr;
Thread pollingThread;
Result signalReturnCode = Result(false);
EventObject refreshSignalFinished;
Mutex mutex;
EventLoopRunner* eventLoopRunner = nullptr;
// Used to pass data from thread to async callback
Notification notification;
FolderWatcher* watcher;
Atomic<bool> closing = false;
//...

Declare only two of the four functions to avoid linker errors.

template <>
void SC::FileSystemWatcher::InternalOpaque::construct(Handle& buffer)
{
placementNew(buffer.reinterpret_as<Object>());
}
template <>
void SC::FileSystemWatcher::InternalOpaque::destruct(Object& obj)
{
obj.~Object();
}

The documentation for this struct was generated from the following file: