Sets - Copy/move cons/ass, comments
This commit is contained in:
parent
a6c068988b
commit
e40417384d
2 changed files with 165 additions and 51 deletions
113
Sets-inline.hh
113
Sets-inline.hh
|
@ -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
103
Sets.hh
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue