Sets - Copy/move cons/ass, comments

This commit is contained in:
Emmanuel BENOîT 2017-11-09 08:51:07 +01:00
parent a6c068988b
commit e40417384d
2 changed files with 165 additions and 51 deletions

View file

@ -11,6 +11,28 @@ namespace ebcl {
/*= SET IMPLEMENTATION - FULLY DYNAMIC ARRAY =================================*/ /*= 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_TMPL_ template< typename Type , uint32_t Growth >
#define M_TYPE_ T_SetImplementation< Type , ArrayBacked< 0 , Growth > > #define M_TYPE_ T_SetImplementation< Type , ArrayBacked< 0 , Growth > >
@ -73,10 +95,28 @@ M_TMPL_ bool M_TYPE_::remove(
/*= SET IMPLEMENTATION - AUTOMATIC ARRAY =====================================*/ /*= 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_TMPL_ template< typename Type , uint32_t ISize , uint32_t Growth >
#define M_TYPE_ T_SetImplementation< Type , ArrayBacked< ISize , Growth > > #define M_TYPE_ T_SetImplementation< Type , ArrayBacked< ISize , Growth > >
M_TMPL_ uint32_t M_TYPE_::size( ) const noexcept M_TMPL_ uint32_t M_TYPE_::size( ) const noexcept
{ {
return data_.size( ); return data_.size( );
@ -124,6 +164,7 @@ M_TMPL_ bool M_TYPE_::remove(
/*= COMMON HANDLER ===========================================================*/ /*= COMMON HANDLER ===========================================================*/
// In-place version
template< typename Type , typename ImplTag > template< typename Type , typename ImplTag >
void T_SetHelper::T_InPlaceHandler< Type , ImplTag >::shdl( void T_SetHelper::T_InPlaceHandler< Type , ImplTag >::shdl(
const E_Operation operation , const E_Operation operation ,
@ -136,7 +177,15 @@ void T_SetHelper::T_InPlaceHandler< Type , ImplTag >::shdl(
switch ( operation ) { switch ( operation ) {
case INIT: 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; break;
case DESTROY: case DESTROY:
@ -171,7 +220,9 @@ void T_SetHelper::T_InPlaceHandler< Type , ImplTag >::shdl(
} }
} }
/*----------------------------------------------------------------------------*/
// Heap-allocated implementation
template< typename Type , typename ImplTag > template< typename Type , typename ImplTag >
void T_SetHelper::T_HeapHandler< Type , ImplTag >::shdl( void T_SetHelper::T_HeapHandler< Type , ImplTag >::shdl(
E_Operation operation , E_Operation operation ,
@ -184,7 +235,15 @@ void T_SetHelper::T_HeapHandler< Type , ImplTag >::shdl(
switch ( operation ) { switch ( operation ) {
case INIT: 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; break;
case DESTROY: case DESTROY:
@ -220,7 +279,7 @@ void T_SetHelper::T_HeapHandler< Type , ImplTag >::shdl(
} }
/*============================================================================*/ /*= T_Set ====================================================================*/
template< typename Type > template< typename Type >
T_Set< Type >::T_Set( ) noexcept T_Set< Type >::T_Set( ) noexcept
@ -232,9 +291,49 @@ template< typename Tag >
T_Set< Type >::T_Set( const UseTag< Tag > ) noexcept T_Set< Type >::T_Set( const UseTag< Tag > ) noexcept
: handler_( T_SetHelper::T_Handler< Type , Tag >::shdl ) : 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 > template< typename Type >
T_Set< Type >::~T_Set( ) T_Set< Type >::~T_Set( )
@ -242,6 +341,8 @@ T_Set< Type >::~T_Set( )
handler_( T_SetHelper::DESTROY , &storage_ , nullptr , nullptr ); handler_( T_SetHelper::DESTROY , &storage_ , nullptr , nullptr );
} }
/*----------------------------------------------------------------------------*/
template< typename Type > template< typename Type >
uint32_t T_Set< Type >::size( ) const noexcept uint32_t T_Set< Type >::size( ) const noexcept
{ {
@ -267,6 +368,8 @@ int32_t T_Set< Type >::indexOf(
return r; return r;
} }
/*----------------------------------------------------------------------------*/
template< typename Type > template< typename Type >
bool T_Set< Type >::add( bool T_Set< Type >::add(
Type const& item ) noexcept Type const& item ) noexcept

103
Sets.hh
View file

@ -30,7 +30,7 @@ struct UseTag
// Implementation of a set of type Type. The actual implementation is // 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 > template< typename Type , typename ImplTag >
class T_SetImplementation; class T_SetImplementation;
@ -44,70 +44,63 @@ M_DEFINE_TEMPLATE_TAG( ArrayBacked ,
//M_DEFINE_TAG( IndexBacked ); //M_DEFINE_TAG( IndexBacked );
template< typename Type , uint32_t InPlace , uint32_t Growth > // Templated horrors used by the main T_Set class.
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;
};
struct T_SetHelper struct T_SetHelper
{ {
// Default implementation to use; also determines the in-place
// storage size
using DefaultImplementation = ArrayBacked< 8 >; // FIXME should use Index by default using DefaultImplementation = ArrayBacked< 8 >; // FIXME should use Index by default
// Default implementation class
template< typename Type template< typename Type
> using DefaultType = T_SetImplementation< > using DefaultType = T_SetImplementation<
Type , DefaultImplementation >; Type , DefaultImplementation >;
template< typename Type // ---------------------------------------------------------------------
> static constexpr auto DefaultSize{ sizeof( DefaultType< Type > ) };
// In-place storage size
template< typename Type 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 enum E_Operation
{ {
// New instance; output = storage
INIT , INIT ,
// Copy instance; output = storage, rArg = source
INIT_COPY ,
// Move instance; output = storage, wArg = source
INIT_MOVE ,
// Destroy instance; wArg = storage
DESTROY , DESTROY ,
// Get size; rArg = storage, output = result
SIZE , SIZE ,
// Get index of element; wArg = storage, rArg = element, output = result
INDEX_OF , INDEX_OF ,
// Add copy of element; wArg = storage, rArg = element, output = result
ADD_COPY , ADD_COPY ,
// Move & add element; wArg = storage, rArg = element, output = result
ADD_MOVE , ADD_MOVE ,
// Delete element; wArg = storage, rArg = element, output = result
REMOVE , 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 template< typename Type , typename Impl
> struct T_InPlaceHandler > struct T_InPlaceHandler
{ {
@ -117,6 +110,7 @@ struct T_SetHelper
void* output ); void* output );
}; };
// Handler for heap-allocated implementations
template< typename Type , typename Impl template< typename Type , typename Impl
> struct T_HeapHandler > struct T_HeapHandler
{ {
@ -126,6 +120,8 @@ struct T_SetHelper
void* output ); 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< template<
typename Type , typename ImplTag , typename Type , typename ImplTag ,
typename Impl = T_SetImplementation< Type , ImplTag > typename Impl = T_SetImplementation< Type , ImplTag >
@ -134,9 +130,6 @@ struct T_SetHelper
T_InPlaceHandler< Type , ImplTag > , T_InPlaceHandler< Type , ImplTag > ,
T_HeapHandler< Type , ImplTag > T_HeapHandler< Type , ImplTag >
>; >;
using F_Handler = std::function<
void( E_Operation , void* , void const* , void* ) >;
}; };
template< typename Type > template< typename Type >
@ -144,30 +137,48 @@ class T_Set
{ {
private: private:
// Storage area for the implementation's data
std::aligned_storage_t< std::aligned_storage_t<
T_SetHelper::DefaultSize< Type > , T_SetHelper::DefaultSize< Type > ,
T_SetHelper::DefaultAlign< Type > T_SetHelper::DefaultAlign< Type >
> storage_; > storage_;
const T_SetHelper::F_Handler handler_;
// Handler
T_SetHelper::F_Handler handler_;
public: public:
// Default constructor, using the default implementation
T_Set( ) noexcept; T_Set( ) noexcept;
// Create a set with a specific implementation
template< typename Tag template< typename Tag
> T_Set( UseTag< Tag > impl ) noexcept; > 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( ); ~T_Set( );
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Returns amount of elements
uint32_t size( ) const noexcept; uint32_t size( ) const noexcept;
// Checks if item is in the set
bool contains( Type const& item ) const noexcept; 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; int32_t indexOf( Type const& item ) const noexcept;
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Add copy of item, returns true if added
bool add( Type const& item ) noexcept; bool add( Type const& item ) noexcept;
// Add moved item, returns true if added
bool add( Type&& item ) noexcept; bool add( Type&& item ) noexcept;
// Remove item, returns true if removed
bool remove( Type const& item ) noexcept; bool remove( Type const& item ) noexcept;
}; };