Log in | Imprint
last updated 9/29/2012 | 922 views
On Twitter
On Vimeo
On YouTube

Particles . C++ Snippets

Code that I keep using throughout various projects and improving over time.

Macros

Compile-time array length, inspired by eXile:

namespace helper
{
template <class T, size_t S> char (&arraylen_helper(T (&a)[S]))[S];
}
#define arraylen(a) sizeof(::helper::arraylen_helper(a))

Emulation of alignas and alignof using the MSVC-specific alignment extensions, inspired by Chris Maiwald:

#define alignas(alignment) __declspec( align(alignment) )

namespace helper
{
// Workaround for Visual Studio Bug: Alignment of some classes
// zero until their size has been evaluated
template <size_t Size, size_t Alignment>
struct alignof_fix
{
static const size_t alignment = Alignment;
};
}

#define alignof(type) ::helper::alignof_fix<sizeof(type), __alignof(type)>::alignment

com_ptr

Pointer class allowing for COM-style object retrieval, e.g. Create***(..., myPtr.rebind());, and providing automated reference counting:

// Allows for customization of reference counting interface via argument-dependent lookup
template <class COMType>
inline void com_acquire(COMType *p)
{
p->AddRef();
}

template <class COMType>
inline void com_release(COMType *p)
{
p->Release();
}

// Allows for binding of existing references without incrementing the reference count
enum bind_reference_t { bind_reference };

template <class COMType>
class com_ptr
{
public:
typedef COMType com_type;
typedef COMType* value_type;

private:
com_type *m_object;

static com_type* acquire_ref(com_type *object)
{
if (object)
com_acquire(object);

return object;
}

static void release_ref(com_type *object)
{
if (object)
com_release(object);
}

public:
com_ptr(com_type *object = nullptr)
: m_object( acquire_ref(object) ) { }
template <class OtherCOMType>
com_ptr(OtherCOMType *object)
: m_object( acquire_ref(object) ) { }

com_ptr(com_type *object, bind_reference_t)
: m_object(object) { }

com_ptr(const com_ptr &right)
: m_object( acquire_ref(right.m_object) ) { }
template <class OtherCOMType>
com_ptr(const com_ptr<OtherCOMType> &right)
: m_object( acquire_ref(right.get()) ) { }

#ifndef CPP11_NO_RVALUE_REFERENCES
template <class OtherCOMType>
com_ptr(com_ptr<OtherCOMType> &&right)
: m_object(right.unbind()) { }
#endif

~com_ptr() throw()
{
release_ref(m_object);
}

void rebind(com_type *object)
{
com_type *prevObject = m_object;
m_object = object;
release_ref(prevObject);
}
com_type* unbind()
{
com_type *preObject = m_object;
m_object = nullptr;
return preObject;
}
void reset(com_type *object)
{
// Do not check for redundant assignment
// -> The code handles redundant assignment just fine
// -> Checking generates up to twice the code due to unfortunate compiler optimization application order
rebind( acquire_ref(object) );
}
void release()
{
rebind(nullptr);
}

com_ptr& operator =(com_type *object)
{
reset(object);
return *this;
}
com_ptr& operator =(const com_ptr &right)
{
reset(right.m_object);
return *this;
}
template <class OtherCOMType>
com_ptr& operator =(const com_ptr<OtherCOMType> &right)
{
reset(right.get());
return *this;
}

#ifndef CPP11_NO_RVALUE_REFERENCES
template <class OtherCOMType>
com_ptr& operator =(com_ptr<OtherCOMType> &&right)
{
// Self-assignment would be wrong
if ((void*) this != (void*) &right)
rebind(right.unbind());

return *this;
}
#endif

com_type*const& get() const { return m_object; }
com_type& operator *() const { return *m_object; }
com_type* operator ->() const { return m_object; }

/// Gets a double-pointer allowing for COM-style object retrieval. The pointer returned may
/// only ever be used until the next call to one of this COM pointer's methods.
com_type** rebind()
{
release();
return &m_object;
}
};
© 2024 Tobias Zirr. All rights reserved.