/******************************************************************************/ /* SETS ***********************************************************************/ /******************************************************************************/ #ifndef _H_EBCL_SETS #define _H_EBCL_SETS #include 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 ); // 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 >; // --------------------------------------------------------------------- // 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 , // 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 { 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 > >; }; 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; // --------------------------------------------------------------------- // 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; }; } #endif // _H_EBCL_SETS // XXX #include #include "Sets-inline.hh"