From e40417384de0b60c833cfd88e345da9081e06797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Thu, 9 Nov 2017 08:51:07 +0100 Subject: [PATCH] Sets - Copy/move cons/ass, comments --- Sets-inline.hh | 113 ++++++++++++++++++++++++++++++++++++++++++++++--- Sets.hh | 103 ++++++++++++++++++++++++-------------------- 2 files changed, 165 insertions(+), 51 deletions(-) diff --git a/Sets-inline.hh b/Sets-inline.hh index 60ca427..ce1d4b1 100644 --- a/Sets-inline.hh +++ b/Sets-inline.hh @@ -11,6 +11,28 @@ namespace ebcl { /*= SET IMPLEMENTATION - FULLY DYNAMIC ARRAY =================================*/ +template< typename Type , uint32_t Growth > +class T_SetImplementation< Type , ArrayBacked< 0 , Growth > > +{ + private: + T_Array< Type > data_; + + public: + template< uint32_t G = Growth , typename std::enable_if_t< G == 0 , int > = 0 + > T_SetImplementation( ) noexcept; + template< uint32_t G = Growth , typename std::enable_if_t< G != 0 , int > = 0 + > T_SetImplementation( ) noexcept; + + uint32_t size( ) const noexcept; + int32_t indexOf( Type const& item ) const noexcept; + + bool add( Type const& item ) noexcept; + bool add( Type&& item ) noexcept; + bool remove( Type const& item ) noexcept; +}; + +/*----------------------------------------------------------------------------*/ + #define M_TMPL_ template< typename Type , uint32_t Growth > #define M_TYPE_ T_SetImplementation< Type , ArrayBacked< 0 , Growth > > @@ -73,10 +95,28 @@ M_TMPL_ bool M_TYPE_::remove( /*= SET IMPLEMENTATION - AUTOMATIC ARRAY =====================================*/ +template< typename Type , uint32_t InPlace , uint32_t Growth > +class T_SetImplementation< Type , ArrayBacked< InPlace , Growth > > +{ + private: + T_AutoArray< Type , InPlace , + Growth == 0 ? ( InPlace * 4 ) : Growth + > data_; + + public: + uint32_t size( ) const noexcept; + int32_t indexOf( Type const& item ) const noexcept; + + bool add( Type const& item ) noexcept; + bool add( Type&& item ) noexcept; + bool remove( Type const& item ) noexcept; +}; + +/*----------------------------------------------------------------------------*/ + #define M_TMPL_ template< typename Type , uint32_t ISize , uint32_t Growth > #define M_TYPE_ T_SetImplementation< Type , ArrayBacked< ISize , Growth > > - M_TMPL_ uint32_t M_TYPE_::size( ) const noexcept { return data_.size( ); @@ -124,6 +164,7 @@ M_TMPL_ bool M_TYPE_::remove( /*= COMMON HANDLER ===========================================================*/ +// In-place version template< typename Type , typename ImplTag > void T_SetHelper::T_InPlaceHandler< Type , ImplTag >::shdl( const E_Operation operation , @@ -136,7 +177,15 @@ void T_SetHelper::T_InPlaceHandler< Type , ImplTag >::shdl( switch ( operation ) { case INIT: - ::new ((char*)wArg) T_Impl_( ); + ::new ((char*)output) T_Impl_( ); + break; + + case INIT_COPY: + ::new ((char*)output) T_Impl_( *(T_Impl_ const*)rArg ); + break; + + case INIT_MOVE: + ::new ((char*)output) T_Impl_( std::move( *(T_Impl_*)wArg ) ); break; case DESTROY: @@ -171,7 +220,9 @@ void T_SetHelper::T_InPlaceHandler< Type , ImplTag >::shdl( } } +/*----------------------------------------------------------------------------*/ +// Heap-allocated implementation template< typename Type , typename ImplTag > void T_SetHelper::T_HeapHandler< Type , ImplTag >::shdl( E_Operation operation , @@ -184,7 +235,15 @@ void T_SetHelper::T_HeapHandler< Type , ImplTag >::shdl( switch ( operation ) { case INIT: - *(T_Impl_**)wArg = new T_Impl_( ); + *(T_Impl_**)output = ::new T_Impl_( ); + break; + + case INIT_COPY: + *(T_Impl_**)output = ::new T_Impl_( *(T_Impl_ const**)rArg ); + break; + + case INIT_MOVE: + *(T_Impl_**)output = ::new T_Impl_( std::move( *(T_Impl_**)wArg ) ); break; case DESTROY: @@ -220,7 +279,7 @@ void T_SetHelper::T_HeapHandler< Type , ImplTag >::shdl( } -/*============================================================================*/ +/*= T_Set ====================================================================*/ template< typename Type > T_Set< Type >::T_Set( ) noexcept @@ -232,9 +291,49 @@ template< typename Tag > T_Set< Type >::T_Set( const UseTag< Tag > ) noexcept : handler_( T_SetHelper::T_Handler< Type , Tag >::shdl ) { - handler_( T_SetHelper::INIT , (char*) &storage_ , nullptr , nullptr ); + handler_( T_SetHelper::INIT , nullptr , nullptr , &storage_ ); } +/*----------------------------------------------------------------------------*/ + +template< typename Type > +T_Set< Type >::T_Set( + T_Set const& other ) noexcept + : handler_( other.handler_ ) +{ + handler_( T_SetHelper::INIT_COPY , nullptr , &other.storage_ , &storage_ ); +} + +template< typename Type > +T_Set< Type >& T_Set< Type >::operator =( + T_Set const& other ) noexcept +{ + handler_( T_SetHelper::DESTROY , &storage_ , nullptr , nullptr ); + handler_ = other.handler_; + handler_( T_SetHelper::INIT_COPY , nullptr , &other.storage_ , &storage_ ); +} + + +/*----------------------------------------------------------------------------*/ + +template< typename Type > +T_Set< Type >::T_Set( + T_Set&& other ) noexcept + : handler_( other.handler_ ) +{ + handler_( T_SetHelper::INIT_MOVE , &other.storage_ , nullptr , &storage_ ); +} + +template< typename Type > +T_Set< Type >& T_Set< Type >::operator =( + T_Set&& other ) noexcept +{ + handler_( T_SetHelper::DESTROY , &storage_ , nullptr , nullptr ); + handler_ = other.handler_; + handler_( T_SetHelper::INIT_MOVE , &other.storage_ , nullptr , &storage_ ); +} + +/*----------------------------------------------------------------------------*/ template< typename Type > T_Set< Type >::~T_Set( ) @@ -242,6 +341,8 @@ T_Set< Type >::~T_Set( ) handler_( T_SetHelper::DESTROY , &storage_ , nullptr , nullptr ); } +/*----------------------------------------------------------------------------*/ + template< typename Type > uint32_t T_Set< Type >::size( ) const noexcept { @@ -267,6 +368,8 @@ int32_t T_Set< Type >::indexOf( return r; } +/*----------------------------------------------------------------------------*/ + template< typename Type > bool T_Set< Type >::add( Type const& item ) noexcept diff --git a/Sets.hh b/Sets.hh index cb1b62e..b6be24b 100644 --- a/Sets.hh +++ b/Sets.hh @@ -30,7 +30,7 @@ struct UseTag // Implementation of a set of type Type. The actual implementation is -// determined by the ImplTag type. +// determined by the ImplTag type template< typename Type , typename ImplTag > class T_SetImplementation; @@ -44,70 +44,63 @@ M_DEFINE_TEMPLATE_TAG( ArrayBacked , //M_DEFINE_TAG( IndexBacked ); -template< typename Type , uint32_t InPlace , uint32_t Growth > -class T_SetImplementation< Type , ArrayBacked< InPlace , Growth > > -{ - private: - T_AutoArray< Type , InPlace , - Growth == 0 ? ( InPlace * 4 ) : Growth - > data_; - - public: - uint32_t size( ) const noexcept; - int32_t indexOf( Type const& item ) const noexcept; - - bool add( Type const& item ) noexcept; - bool add( Type&& item ) noexcept; - bool remove( Type const& item ) noexcept; -}; - -template< typename Type , uint32_t Growth > -class T_SetImplementation< Type , ArrayBacked< 0 , Growth > > -{ - private: - T_Array< Type > data_; - - public: - template< uint32_t G = Growth , typename std::enable_if_t< G == 0 , int > = 0 - > T_SetImplementation( ) noexcept; - template< uint32_t G = Growth , typename std::enable_if_t< G != 0 , int > = 0 - > T_SetImplementation( ) noexcept; - - uint32_t size( ) const noexcept; - int32_t indexOf( Type const& item ) const noexcept; - - bool add( Type const& item ) noexcept; - bool add( Type&& item ) noexcept; - bool remove( Type const& item ) noexcept; -}; - +// Templated horrors used by the main T_Set class. struct T_SetHelper { + // Default implementation to use; also determines the in-place + // storage size using DefaultImplementation = ArrayBacked< 8 >; // FIXME should use Index by default + // Default implementation class template< typename Type > using DefaultType = T_SetImplementation< Type , DefaultImplementation >; - template< typename Type - > static constexpr auto DefaultSize{ sizeof( DefaultType< Type > ) }; + // --------------------------------------------------------------------- + // In-place storage size template< typename Type - > static constexpr auto DefaultAlign{ alignof( DefaultType< Type > ) }; + > static constexpr auto DefaultSize{ + sizeof( DefaultType< Type > ) }; + // In-place storage alignment + template< typename Type + > static constexpr auto DefaultAlign{ + alignof( DefaultType< Type > ) }; + // --------------------------------------------------------------------- + + // Implementation handler operations enum E_Operation { + // New instance; output = storage INIT , + // Copy instance; output = storage, rArg = source + INIT_COPY , + // Move instance; output = storage, wArg = source + INIT_MOVE , + // Destroy instance; wArg = storage DESTROY , + // Get size; rArg = storage, output = result SIZE , + // Get index of element; wArg = storage, rArg = element, output = result INDEX_OF , + // Add copy of element; wArg = storage, rArg = element, output = result ADD_COPY , + // Move & add element; wArg = storage, rArg = element, output = result ADD_MOVE , + // Delete element; wArg = storage, rArg = element, output = result REMOVE , }; + // Handler function type + using F_Handler = std::function< + void( E_Operation , void* , void const* , void* ) >; + + // --------------------------------------------------------------------- + + // Handler for in-place implementations template< typename Type , typename Impl > struct T_InPlaceHandler { @@ -117,6 +110,7 @@ struct T_SetHelper void* output ); }; + // Handler for heap-allocated implementations template< typename Type , typename Impl > struct T_HeapHandler { @@ -126,6 +120,8 @@ struct T_SetHelper void* output ); }; + // Use the in-place handler if the implementation data can fit into the + // in-place storage; otherwise use the heap-allocated handler. template< typename Type , typename ImplTag , typename Impl = T_SetImplementation< Type , ImplTag > @@ -134,9 +130,6 @@ struct T_SetHelper T_InPlaceHandler< Type , ImplTag > , T_HeapHandler< Type , ImplTag > >; - - using F_Handler = std::function< - void( E_Operation , void* , void const* , void* ) >; }; template< typename Type > @@ -144,30 +137,48 @@ class T_Set { private: + // Storage area for the implementation's data std::aligned_storage_t< T_SetHelper::DefaultSize< Type > , T_SetHelper::DefaultAlign< Type > > storage_; - const T_SetHelper::F_Handler handler_; + + // Handler + T_SetHelper::F_Handler handler_; public: + // Default constructor, using the default implementation T_Set( ) noexcept; - + // Create a set with a specific implementation template< typename Tag > T_Set( UseTag< Tag > impl ) noexcept; + // Copy constructor / assignment + T_Set( T_Set const& other ) noexcept; + T_Set& operator =( T_Set const& other ) noexcept; + + // Move constructor / assignment + T_Set( T_Set&& other ) noexcept; + T_Set& operator =( T_Set&& other ) noexcept; + ~T_Set( ); // --------------------------------------------------------------------- + // Returns amount of elements uint32_t size( ) const noexcept; + // Checks if item is in the set bool contains( Type const& item ) const noexcept; + // Returns underlying index of item, or -1 if not in the set int32_t indexOf( Type const& item ) const noexcept; // --------------------------------------------------------------------- + // Add copy of item, returns true if added bool add( Type const& item ) noexcept; + // Add moved item, returns true if added bool add( Type&& item ) noexcept; + // Remove item, returns true if removed bool remove( Type const& item ) noexcept; };