Skip to content

Instantly share code, notes, and snippets.

@Ed94
Last active December 6, 2024 01:54
Show Gist options
  • Select an option

  • Save Ed94/23ab8e5aa534114e2a5a48f037e065e2 to your computer and use it in GitHub Desktop.

Select an option

Save Ed94/23ab8e5aa534114e2a5a48f037e065e2 to your computer and use it in GitHub Desktop.
_Generic function overloading example in C11
#pragma region Array_ssize
#define GENERIC_SLOT_2__array_init Array_ssize, Array_ssize_init
#define GENERIC_SLOT_2__array_init_reserve Array_ssize, Array_ssize_init_reserve
#define GENERIC_SLOT_2__array_append Array_ssize, Array_ssize_append
#define GENERIC_SLOT_2__array_append_items Array_ssize, Array_ssize_append_items
#define GENERIC_SLOT_2__array_append_at Array_ssize, Array_ssize_append_at
#define GENERIC_SLOT_2__array_append_items_at Array_ssize, Array_ssize_append_items_at
#define GENERIC_SLOT_2__array_back Array_ssize, Array_ssize_back
#define GENERIC_SLOT_2__array_clear Array_ssize, Array_ssize_clear
#define GENERIC_SLOT_2__array_fill Array_ssize, Array_ssize_fill
#define GENERIC_SLOT_2__array_free Array_ssize, Array_ssize_free
#define GENERIC_SLOT_2__array_grow Array_ssize*, Array_ssize_grow
#define GENERIC_SLOT_2__array_num Array_ssize, Array_ssize_num
#define GENERIC_SLOT_2__array_pop Array_ssize, Array_ssize_pop
#define GENERIC_SLOT_2__array_remove_at Array_ssize, Array_ssize_remove_at
#define GENERIC_SLOT_2__array_reserve Array_ssize, Array_ssize_reserve
#define GENERIC_SLOT_2__array_resize Array_ssize, Array_ssize_resize
#define GENERIC_SLOT_2__array_set_capacity Array_ssize*, Array_ssize_set_capacity
typedef ssize* Array_ssize;
Array_ssize Array_ssize_init( AllocatorInfo allocator );
Array_ssize Array_ssize_init_reserve( AllocatorInfo allocator, usize capacity );
bool Array_ssize_append_array( Array_ssize* self, Array_ssize other );
bool Array_ssize_append( Array_ssize* self, ssize value );
bool Array_ssize_append_items( Array_ssize* self, ssize* items, usize item_num );
bool Array_ssize_append_at( Array_ssize* self, ssize item, usize idx );
bool Array_ssize_append_items_at( Array_ssize* self, ssize* items, usize item_num, usize idx );
ssize* Array_ssize_back( Array_ssize self );
void Array_ssize_clear( Array_ssize self );
bool Array_ssize_fill( Array_ssize self, usize begin, usize end, ssize value );
void Array_ssize_free( Array_ssize* self );
bool Array_ssize_grow( Array_ssize* self, usize min_capacity );
usize Array_ssize_num( Array_ssize self );
ssize Array_ssize_pop( Array_ssize self );
void Array_ssize_remove_at( Array_ssize self, usize idx );
bool Array_ssize_reserve( Array_ssize* self, usize new_capacity );
bool Array_ssize_resize( Array_ssize* self, usize num );
bool Array_ssize_set_capacity( Array_ssize* self, usize new_capacity );
forceinline Array_ssize Array_ssize_init( AllocatorInfo allocator )
{
size_t initial_size = array_grow_formula( 0 );
return array_init_reserve( Array_ssize, allocator, initial_size );
}
inline Array_ssize Array_ssize_init_reserve( AllocatorInfo allocator, usize capacity )
{
GEN_ASSERT( capacity > 0 );
ArrayHeader* header = rcast( ArrayHeader*, alloc( allocator, sizeof( ArrayHeader ) + sizeof( ssize ) * capacity ) );
if ( header == nullptr )
return nullptr;
header->Allocator = allocator;
header->Capacity = capacity;
header->Num = 0;
return rcast( ssize*, header + 1 );
}
forceinline bool Array_ssize_append_array( Array_ssize* self, Array_ssize other )
{
return array_append_items( *self, (Array_ssize)other, Array_ssize_num( other ) );
}
inline bool Array_ssize_append( Array_ssize* self, ssize value )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( *self != nullptr );
ArrayHeader* header = array_get_header( *self );
if ( header->Num == header->Capacity )
{
if ( ! array_grow( self, header->Capacity ) )
return false;
header = array_get_header( *self );
}
( *self )[header->Num] = value;
header->Num++;
return true;
}
inline bool Array_ssize_append_items( Array_ssize* self, ssize* items, usize item_num )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( *self != nullptr );
GEN_ASSERT( items != nullptr );
GEN_ASSERT( item_num > 0 );
ArrayHeader* header = array_get_header( *self );
if ( header->Num + item_num > header->Capacity )
{
if ( ! array_grow( self, header->Capacity + item_num ) )
return false;
header = array_get_header( *self );
}
mem_copy( ( *self ) + header->Num, items, sizeof( ssize ) * item_num );
header->Num += item_num;
return true;
}
inline bool Array_ssize_append_at( Array_ssize* self, ssize item, usize idx )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( *self != nullptr );
ArrayHeader* header = array_get_header( *self );
if ( idx >= header->Num )
idx = header->Num - 1;
if ( idx < 0 )
idx = 0;
if ( header->Capacity < header->Num + 1 )
{
if ( ! array_grow( self, header->Capacity + 1 ) )
return false;
header = array_get_header( *self );
}
Array_ssize target = ( *self ) + idx;
mem_move( target + 1, target, ( header->Num - idx ) * sizeof( ssize ) );
header->Num++;
return true;
}
inline bool Array_ssize_append_items_at( Array_ssize* self, ssize* items, usize item_num, usize idx )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( *self != nullptr );
ArrayHeader* header = array_get_header( *self );
if ( idx >= header->Num )
{
return array_append_items( *self, items, item_num );
}
if ( item_num > header->Capacity )
{
if ( ! array_grow( self, item_num + header->Capacity ) )
return false;
header = array_get_header( *self );
}
ssize* target = ( *self ) + idx + item_num;
ssize* src = ( *self ) + idx;
mem_move( target, src, ( header->Num - idx ) * sizeof( ssize ) );
mem_copy( src, items, item_num * sizeof( ssize ) );
header->Num += item_num;
return true;
}
inline ssize* Array_ssize_back( Array_ssize self )
{
GEN_ASSERT( self != nullptr );
ArrayHeader* header = array_get_header( self );
if ( header->Num == 0 )
return 0;
return self + header->Num - 1;
}
inline void Array_ssize_clear( Array_ssize self )
{
GEN_ASSERT( self != nullptr );
ArrayHeader* header = array_get_header( self );
header->Num = 0;
}
inline bool Array_ssize_fill( Array_ssize self, usize begin, usize end, ssize value )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( begin <= end );
ArrayHeader* header = array_get_header( self );
if ( begin < 0 || end >= header->Num )
return false;
for ( ssize idx = begin; idx < end; idx++ )
self[idx] = value;
return true;
}
inline void Array_ssize_free( Array_ssize* self )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( *self != nullptr );
ArrayHeader* header = array_get_header( *self );
allocator_free( header->Allocator, header );
self = 0;
}
inline bool Array_ssize_grow( Array_ssize* self, usize min_capacity )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( *self != nullptr );
GEN_ASSERT( min_capacity > 0 );
ArrayHeader* header = array_get_header( *self );
usize new_capacity = array_grow_formula( header->Capacity );
if ( new_capacity < min_capacity )
new_capacity = min_capacity;
return array_set_capacity( self, new_capacity );
}
forceinline usize Array_ssize_num( Array_ssize self )
{
GEN_ASSERT( self != nullptr );
return array_get_header( self )->Num;
}
inline ssize Array_ssize_pop( Array_ssize self )
{
GEN_ASSERT( self != nullptr );
ArrayHeader* header = array_get_header( self );
GEN_ASSERT( header->Num > 0 );
ssize result = self[header->Num - 1];
header->Num--;
return result;
}
forceinline void Array_ssize_remove_at( Array_ssize self, usize idx )
{
GEN_ASSERT( self != nullptr );
ArrayHeader* header = array_get_header( self );
GEN_ASSERT( idx < header->Num );
mem_move( self + idx, self + idx + 1, sizeof( ssize ) * ( header->Num - idx - 1 ) );
header->Num--;
}
inline bool Array_ssize_reserve( Array_ssize* self, usize new_capacity )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( *self != nullptr );
GEN_ASSERT( new_capacity > 0 );
ArrayHeader* header = array_get_header( *self );
if ( header->Capacity < new_capacity )
return array_set_capacity( self, new_capacity );
return true;
}
inline bool Array_ssize_resize( Array_ssize* self, usize num )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( *self != nullptr );
GEN_ASSERT( num > 0 );
ArrayHeader* header = array_get_header( *self );
if ( header->Capacity < num )
{
if ( ! array_grow( self, num ) )
return false;
header = array_get_header( *self );
}
header->Num = num;
return true;
}
inline bool Array_ssize_set_capacity( Array_ssize* self, usize new_capacity )
{
GEN_ASSERT( self != nullptr );
GEN_ASSERT( *self != nullptr );
GEN_ASSERT( new_capacity > 0 );
ArrayHeader* header = array_get_header( *self );
if ( new_capacity == header->Capacity )
return true;
if ( new_capacity < header->Num )
{
header->Num = new_capacity;
return true;
}
usize size = sizeof( ArrayHeader ) + sizeof( ssize ) * new_capacity;
ArrayHeader* new_header = cast( ArrayHeader*, alloc( header->Allocator, size ) );
if ( new_header == 0 )
return false;
mem_move( new_header, header, sizeof( ArrayHeader ) + sizeof( ssize ) * header->Num );
new_header->Capacity = new_capacity;
allocator_free( header->Allocator, &header );
*self = cast( ssize*, new_header + 1 );
return true;
}
#pragma endregion Array_ssize
typedef struct ArrayHeader ArrayHeader;
struct ArrayHeader
{
AllocatorInfo Allocator;
usize Capacity;
usize Num;
};
#define array_grow_formula( value ) ( 2 * value + 8 )
#define array_get_header( self ) ( (ArrayHeader*)( self ) - 1 )
#define array_init( selector_arg, ... ) \
_Generic( \
( *(selector_arg*)NULL ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_init ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_init ) \
) GEN_RESOLVED_FUNCTION_CALL( __VA_ARGS__ )
#define array_init_reserve( selector_arg, ... ) \
_Generic( \
( *(selector_arg*)NULL ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_init_reserve ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_init_reserve ) \
) GEN_RESOLVED_FUNCTION_CALL( __VA_ARGS__ )
#define array_append( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_append ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_append ) \
) GEN_RESOLVED_FUNCTION_CALL( &selector_arg, __VA_ARGS__ )
#define array_append_items( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_append_items ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_append_items ) \
) GEN_RESOLVED_FUNCTION_CALL( &selector_arg, __VA_ARGS__ )
#define array_back( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_back ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_back ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARGS__ )
#define array_clear( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_clear ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_clear ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARGS__ )
#define array_fill( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_fill ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_fill ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARGS__ )
#define array_free( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_free ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_free ) \
) GEN_RESOLVED_FUNCTION_CALL( &selector_arg )
#define array_grow( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_grow ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_grow ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARGS__ )
#define array_num( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_num ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_num ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARGS__ )
#define array_pop( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_pop ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_pop ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARGS__ )
#define array_remove_at( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_remove_at ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_remove_at ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARGS__ )
#define array_reserve( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_reserve ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_reserve ) \
) GEN_RESOLVED_FUNCTION_CALL( &selector_arg, __VA_ARGS__ )
#define array_set_capacity( selector_arg, ... ) \
_Generic( \
( selector_arg ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__array_set_capacity ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( GENERIC_SLOT_2__array_set_capacity ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARGS__ )
#if GEN_COMPILER_C
// ------------------------ _Generic function overloading -----------------------------------------
// This implemnents macros for utilizing "The Naive Extendible _Generic Macro" explained in:
// https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md
// Since gencpp is used to generate the c-library, it was choosen over the more novel implementations to keep the macros as easy to understand and unopaque as possible.
// Extensive effort was put in below to make this as easy as possible to understand what is going on with this mess of a preoprocessor.
// Where the signature would be defined using:
#define GEN_TYPE_TO_EXP(type) (type*)NULL
#define GEN_COMMA_OPERATOR , // The comma operator is used by preprocessor macros to delimit arguments, so we have to represent it via a macro to prevent parsing incorrectly.
// Helper macros for argument selection
#define GEN_SELECT_ARG_1( _1, ... ) _1 // <-- Of all th args passed pick _1.
#define GEN_SELECT_ARG_2( _1, _2, ... ) _2 // <-- Of all the args passed pick _2.
#define GEN_SELECT_ARG_3( _1, _2, _3, ... ) _3 // etc.. (by induction until _8, which we don't support any more beyond)
// #define GEN_SELECT_ARG_4( _1, _2, _3, _4, ... ) _4
// #define GEN_SELECT_ARG_5( _1, _2, _3, _4, _5, ... ) _5
// #define GEN_SELECT_ARG_6( _1, _2, _3, _4, _5, _6, ... ) _6
// #define GEN_SELECT_ARG_7( _1, _2, _3, _4, _5, _6, _7, ... ) _7
// #define GEN_SELECT_ARG_8( _1, _2, _3, _4, _5, _6, _7, _8, ... ) _8
#define GEN_GENERIC_SEL_ENTRY_TYPE GEN_SELECT_ARG_1 // Use the arg expansion macro to select arg 1 which should have the type.
#define GEN_GENERIC_SEL_ENTRY_FUNCTION GEN_SELECT_ARG_2 // Use the arg expansion macro to select arg 2 which should have the function.
#define GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER GEN_SELECT_ARG_3 // Use the arg expansion macro to select arg 3 which should have the comma delimiter ','.
#define GEN_RESOLVED_FUNCTION_CALL // Just used to indicate where the call "occurs"
// ----------------------------------------------------------------------------------------------------------------------------------
// GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( macro ) includes a _Generic slot only if the specified macro is defined (as type, function_name).
// It takes advantage of the fact that if the macro is defined, then the expanded text will contain a comma.
// Expands to ',' if it can find (type): (function) <comma_operator: ',' >
// Where GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER is specifically looking for that <comma> ,
#define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ) GEN_COMMA_OPERATOR, , )
// ^ Selects the comma ^ is the type ^ is the function ^ Insert a comma
// The slot won't exist if that comma is not found. |
// |
// This is the same as above but it does not insert a comma V no comma here.
#define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ), , )
// Needed for the last slot as they don't allow trailing commas.
// ----------------------------------------------------------------------------------------------------------------------------------
// Below are generated on demand for an overlaod depdendent on a type:
// ----------------------------------------------------------------------------------------------------------------------------------
#define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic( \
(selector_arg), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(FunctionID__ARGS_SIG_1 ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg )
// ----------------------------------------------------------------------------------------------------------------------------------
// Then each definiton of a function has an associated define:
// #define <function_id_macro> GEN_GENERIC_FUNCTION_ARG_SIGNATURE( <function_id>, <arguments> )
#define GEN_GENERIC_FUNCTION_ARG_SIGNATURE( name_of_function, type_delimiter ) type_delimiter name_of_function
// Then somehwere later on
// <etc> <return_type> <function_id> ( <arguments> ) { <implementation> }
// Concrete example:
// To add support for long:
#define GEN_EXAMPLE_HASH__ARGS_SIG_1 GEN_GENERIC_FUNCTION_ARG_SIGNATURE( hash__P_long, long long )
size_t gen_example_hash__P_long( long val ) { return val * 2654435761ull; }
// To add support for long long:
#define GEN_EXAMPLE_HASH__ARGS_SIG_2 GEN_GENERIC_FUNCTION_ARG_SIGNATURE( hash__P_long_long, long long )
size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761ull; }
// If using an Editor with support for syntax hightlighting macros: HASH__ARGS_SIG_1 and HASH_ARGS_SIG_2 should show color highlighting indicating the slot is enabled,
// or, "defined" for usage during the compilation pass that handles the _Generic instrinsic.
#define hash( function_arguments ) _Generic( \
(function_arguments), /* Select Via Expression*/ \
/* Extendibility slots: */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_2 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_3 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_4 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_5 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_6 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( HASH__ARGS_SIG_7 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST( HASH__ARGS_SIG_8 ) \
) GEN_RESOLVED_FUNCTION_CALL( function_arguments )
// Additional Variations:
// If the function takes more than one argument the following is used:
#define GEN_FUNCTION_GENERIC_EXAMPLE_VARADIC( selector_arg, ... ) _Generic( \
(selector_arg), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 ) \
... \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(FunctionID__ARGS_SIG_N ) \
) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARG__ )
// If the function does not take the arugment as a parameter:
#define GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( selector_arg ) _Generic( \
( GEN_TYPE_TO_EXP(selector_arg) ), \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_1 ) \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( FunctionID__ARGS_SIG_2 ) \
/* ... */ \
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT_LAST(FunctionID__ARGS_SIG_N ) \
) GEN_RESOLVED_FUNCTION_CALL()
// typedef void* GEN_GenericExampleType;
// GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( GEN_GenericExampleType );
// END OF ------------------------ _Generic function overloading ----------------------------------------- END OF
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment