Skip to content

Instantly share code, notes, and snippets.

@abergmeier
Last active September 27, 2020 08:46
Show Gist options
  • Save abergmeier/6778064 to your computer and use it in GitHub Desktop.
Save abergmeier/6778064 to your computer and use it in GitHub Desktop.
Initial for hiding implementation.
#pragma once
#include <type_traits>
#include <cstddef>
#include <cassert>
#include <memory>
namespace ab {
template< typename T, std::size_t Bytes >
struct fits_in_storage : public std::integral_constant<bool, sizeof(typename std::aligned_storage<Bytes, 1>::type) >= sizeof(typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type)>
{};
struct cookie {
typedef void (*deleter_type)(void*);
typedef std::unique_ptr<void, deleter_type> unique_ptr;
cookie();
cookie( unique_ptr ptr );
cookie( void* ptr, deleter_type );
cookie( cookie&& );
cookie& operator=( cookie&& );
template< typename T >
T* release() {
return static_cast<T*>( _internal.release() );
}
private:
cookie( const cookie &);
cookie& operator=( const cookie& );
unique_ptr _internal;
};
// Class for hiding class implementation details from signature.
// Deriving reserves buffer of Bytes in the class, where internal data might be stored.
template< std::size_t Bytes >
struct anon_impl {
anon_impl() {}
typedef cookie cookie_type;
// Retrieve a previously constructed object of type T
template< typename T >
T& get() {
// If the assert triggers you have to increase Bytes
static_assert( fits_in_storage<T, Bytes>::value, "Not enough space to put type into storage" );
return *reinterpret_cast<T*>( &_storage );
}
// Instantiate an object T in reserved buffer
template< typename T, typename... Arguments >
cookie_type make_stored( Arguments&& args ) {
new ( &get<T>() ) T( std::forward<Arguments>(args)... );
return create_cookie<T>();
}
private:
template< typename T >
static void cookie_delete( void* ptr ) {
static_cast<T*>( ptr )->~T();
}
template< typename T >
cookie_type create_cookie() {
return cookie_type(
&get<T>(),
cookie_delete<T>
);
}
anon_impl( const anon_impl& );
typename std::aligned_storage<Bytes, 1>::type _storage;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment