corelib/include/ebcl/Sets.hh

196 lines
5.6 KiB
C++

/******************************************************************************/
/* SETS ***********************************************************************/
/******************************************************************************/
#ifndef _H_EBCL_SETS
#define _H_EBCL_SETS
#include <ebcl/Arrays.hh>
#include <ebcl/HashIndex.hh>
namespace ebcl {
/*= SETS =====================================================================*/
// Implementation of a set of type Type. The actual implementation is
// determined by the ImplTag type
template< typename Type , typename ImplTag >
class T_SetImplementation;
// ArrayBacked implementation tag. InPlace is the amount of items to
// store in-place (0 will cause a fully dynamic array to be used)
M_DEFINE_TEMPLATE_TAG( ArrayBacked ,
uint32_t InPlace ,
uint32_t Growth = 0
);
// IndexBacked implementation tag - the implementation will use a
// T_HashIndex and an array. InitialSize and HashSize affect the index,
// Growth affects both the index and the array.
M_DEFINE_TEMPLATE_TAG( IndexBacked ,
uint32_t InitialSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t HashSize = T_HashIndex::DEFAULT_SIZE ,
uint32_t Growth = T_HashIndex::DEFAULT_GROWTH );
/*----------------------------------------------------------------------------*/
// 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 = IndexBacked< >;
// Default implementation class
template< typename Type
> using DefaultType = T_SetImplementation<
Type , DefaultImplementation >;
// ---------------------------------------------------------------------
// In-place storage size
template< typename 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 ,
// Access an element; wArg = index , rArg = storage, output = pointer
ACCESS ,
// 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 ,
// Free memory; wArg = storage
FREE ,
// Clear contents; wArg = storage
CLEAR ,
};
// 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
{
static void shdl( E_Operation operation ,
void* wArg ,
void const* rArg ,
void* output );
};
// Handler for heap-allocated implementations
template< typename Type , typename Impl
> struct T_HeapHandler
{
static void shdl( E_Operation operation ,
void* wArg ,
void const* rArg ,
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 >
> using T_Handler = std::conditional_t<
sizeof( Impl ) <= DefaultSize< Type > ,
T_InPlaceHandler< Type , ImplTag > ,
T_HeapHandler< Type , ImplTag >
>;
};
/*----------------------------------------------------------------------------*/
// A set of elements of type Type
template< typename Type
> class T_Set
{
private:
// Storage area for the implementation's data
std::aligned_storage_t<
T_SetHelper::DefaultSize< Type > ,
T_SetHelper::DefaultAlign< Type >
> storage_;
// 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;
// Access an element using its underlying index
Type const& operator[]( uint32_t index ) 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;
// ---------------------------------------------------------------------
void clear( ) noexcept;
void free( ) noexcept;
};
}
#endif // _H_EBCL_SETS
#include <ebcl/inline/Sets.hh>