Last active
September 27, 2020 08:46
-
-
Save abergmeier/6778064 to your computer and use it in GitHub Desktop.
Initial for hiding implementation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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