180 lines
4.3 KiB
C++
180 lines
4.3 KiB
C++
|
/******************************************************************************/
|
||
|
/* SETS ***********************************************************************/
|
||
|
/******************************************************************************/
|
||
|
|
||
|
#ifndef _H_EBCL_SETS
|
||
|
#define _H_EBCL_SETS
|
||
|
#include <ebcl/Arrays.hh>
|
||
|
namespace ebcl {
|
||
|
|
||
|
// FIXME move this to utilities \/
|
||
|
|
||
|
// Define a structure that can be used as a tag
|
||
|
#define M_DEFINE_TAG( NAME ) \
|
||
|
struct NAME { }
|
||
|
// Define a tag structure that can carry arguments
|
||
|
#define M_DEFINE_TEMPLATE_TAG( NAME , ARGS... ) \
|
||
|
template< ARGS > \
|
||
|
M_DEFINE_TAG( NAME )
|
||
|
|
||
|
// A structure that can be used to carry a tag structure instance
|
||
|
template< typename Tag >
|
||
|
struct UseTag
|
||
|
{
|
||
|
const Tag tag;
|
||
|
|
||
|
template< typename ... ArgTypes >
|
||
|
constexpr UseTag( ArgTypes&&... args ) noexcept
|
||
|
: tag( std::forward< ArgTypes >( args ) ... ) { }
|
||
|
};
|
||
|
|
||
|
|
||
|
// 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 T_Array to be used
|
||
|
M_DEFINE_TEMPLATE_TAG( ArrayBacked ,
|
||
|
uint32_t InPlace ,
|
||
|
uint32_t Growth = 0
|
||
|
);
|
||
|
//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;
|
||
|
};
|
||
|
|
||
|
struct T_SetHelper
|
||
|
{
|
||
|
using DefaultImplementation = ArrayBacked< 8 >; // FIXME should use Index by default
|
||
|
|
||
|
template< typename Type
|
||
|
> using DefaultType = T_SetImplementation<
|
||
|
Type , DefaultImplementation >;
|
||
|
|
||
|
template< typename Type
|
||
|
> static constexpr auto DefaultSize{ sizeof( DefaultType< Type > ) };
|
||
|
|
||
|
template< typename Type
|
||
|
> static constexpr auto DefaultAlign{ alignof( DefaultType< Type > ) };
|
||
|
|
||
|
enum E_Operation
|
||
|
{
|
||
|
INIT ,
|
||
|
DESTROY ,
|
||
|
|
||
|
SIZE ,
|
||
|
INDEX_OF ,
|
||
|
|
||
|
ADD_COPY ,
|
||
|
ADD_MOVE ,
|
||
|
REMOVE ,
|
||
|
};
|
||
|
|
||
|
template< typename Type , typename Impl
|
||
|
> struct T_InPlaceHandler
|
||
|
{
|
||
|
static void shdl( E_Operation operation ,
|
||
|
void* wArg ,
|
||
|
void const* rArg ,
|
||
|
void* output );
|
||
|
};
|
||
|
|
||
|
template< typename Type , typename Impl
|
||
|
> struct T_HeapHandler
|
||
|
{
|
||
|
static void shdl( E_Operation operation ,
|
||
|
void* wArg ,
|
||
|
void const* rArg ,
|
||
|
void* output );
|
||
|
};
|
||
|
|
||
|
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 >
|
||
|
>;
|
||
|
|
||
|
using F_Handler = std::function<
|
||
|
void( E_Operation , void* , void const* , void* ) >;
|
||
|
};
|
||
|
|
||
|
template< typename Type >
|
||
|
class T_Set
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
std::aligned_storage_t<
|
||
|
T_SetHelper::DefaultSize< Type > ,
|
||
|
T_SetHelper::DefaultAlign< Type >
|
||
|
> storage_;
|
||
|
const T_SetHelper::F_Handler handler_;
|
||
|
|
||
|
public:
|
||
|
T_Set( ) noexcept;
|
||
|
|
||
|
template< typename Tag
|
||
|
> T_Set( UseTag< Tag > impl ) noexcept;
|
||
|
|
||
|
~T_Set( );
|
||
|
|
||
|
// ---------------------------------------------------------------------
|
||
|
|
||
|
uint32_t size( ) const noexcept;
|
||
|
bool contains( Type const& item ) 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;
|
||
|
};
|
||
|
|
||
|
|
||
|
}
|
||
|
#endif // _H_EBCL_SETS
|
||
|
// XXX #include <ebcl/inline/Sets.hh>
|
||
|
#include "Sets-inline.hh"
|
||
|
|