Last active
February 12, 2025 04:43
Revisions
-
Ed94 revised this gist
Feb 12, 2025 . No changes.There are no files selected for viewing
-
Ed94 revised this gist
Feb 12, 2025 . 1 changed file with 5 additions and 7 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -16,9 +16,7 @@ // -------------------------------------------------------------------------------------------------------------------------------------------- // For explanation of intended usage with staged metaprogramming see: https://github.com/Ed94/gencpp/tree/main/gen_c_library#macro-usage // Techncially this can be used for more than just implementing function overloading. // Additional info: https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/ // -------------------------------------------------------------------------------------------------------------------------------------------- #ifndef COMMA_OPERATOR @@ -141,10 +139,10 @@ size_t generic_example_hash__P_long_long( long long val ) { return val * 2654435 S64 : example_with_s64, \ default: assert_generic_sel_fail \ ) #define example_with(expr) \ _Generic((expr), \ SSIZE : example_with_SSIZEZ \ default : example_with_not_SSIZE(allocator, in) \ ) generic_call(allocator, in) // This can be made more concise with he following "layer" indicating _Generic macros -
Ed94 revised this gist
Feb 12, 2025 . 1 changed file with 25 additions and 24 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,7 +4,6 @@ // or have their usage removed during the library generation pass. #endif // ____ _ ______ _ _ ____ _ __ _ // / ___} (_) | ____} | | (_) / __ \ | | | |(_) // | | ___ ___ _ __ ___ _ __ _ ___ | |__ _ _ _ __ ___| |_ _ ___ _ __ | | | |_ _____ _ __ | | ___ __ _ __| | _ _ __ __ _ @@ -17,7 +16,7 @@ // -------------------------------------------------------------------------------------------------------------------------------------------- // For explanation of intended usage with staged metaprogramming see: https://github.com/Ed94/gencpp/tree/main/gen_c_library#macro-usage // Techncially this can be used for more than just implementing function overloading. // Additional info: // https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/ // https://medium.com/@pauljlucas/generic-in-c-d7ab47e3b5ab // -------------------------------------------------------------------------------------------------------------------------------------------- @@ -37,8 +36,8 @@ #define generic_sel_entry_comma_delimiter select_arg_3 // Use the arg expansion macro to select arg 3 which should have the comma delimiter ','. #endif #ifndef generic_call #define generic_call // Just used to indicate where the call "occurs" #endif // ---------------------------------------------------------------------------------------------------------------------------------- @@ -57,8 +56,8 @@ typedef struct UNRESOLVED_GENERIC_SELECTION UNRESOLVED_GENERIC_SELECTION; struct UNRESOLVED_GENERIC_SELECTION { void* _THE_VOID_SLOT_; }; UNRESOLVED_GENERIC_SELECTION const assert_generic_sel_fail = {0}; // Which will provide the message: error: called object type 'struct NO_RESOLVED_GENERIC_SELECTION' is not a function or function pointer // ---------------------------------------------------------------------------------------------------------------------------------- // Below are generated on demand for an overlaod depdendent on a type: @@ -68,8 +67,8 @@ UNRESOLVED_GENERIC_SELECTION const assert_generic_selection_fail = {0}; /* Extendibility slots: */ \ if_generic_selector_defined_include_slot( GENERIC_SLOT_1__function_sig ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_2__function_sig ) \ default: assert_generic_sel_fail \ ) generic_call( selector_arg ) // ---------------------------------------------------------------------------------------------------------------------------------- // Then each definiton of a function has an associated define: @@ -81,17 +80,17 @@ UNRESOLVED_GENERIC_SELECTION const assert_generic_selection_fail = {0}; // Concrete example: // To add support for long: #define GENERIC_SLOT_1__example_hash long, generic_example_hash__P_long size_t generic_example_hash__P_long( long val ) { return val * 2654435761ull; } // To add support for long long: #define GENERIC_SLOT_2__example_hash long long, generic_example_hash__P_long_long size_t generic_example_hash__P_long_long( long long val ) { return val * 2654435761ull; } // If using an Editor with support for syntax hightlighting macros: // GENERIC_SLOT_1__example_hash and GENERIC_SLOT_2__example_hash should show color highlighting indicating the slot is enabled, // or, "defined" for usage during the compilation pass that handles the _Generic instrinsic. #define generic_example_hash( function_arguments ) _Generic( \ (function_arguments), /* Select Via Expression*/ \ /* Extendibility slots: */ \ if_generic_selector_defined_include_slot( GENERIC_SLOT_1__example_hash ) \ @@ -102,8 +101,8 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; if_generic_selector_defined_include_slot( GENERIC_SLOT_6__example_hash ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_7__example_hash ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_8__example_hash ) \ default: assert_generic_sel_fail \ ) generic_call( function_arguments ) // Additional Variations: @@ -114,8 +113,8 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; if_generic_selector_defined_include_slot( GENERIC_SLOT_2__function_sig ) \ /* ... */ \ if_generic_selector_defined_include_slot(GENERIC_SLOT_N__function_sig ) \ default: assert_generic_sel_fail \ ) generic_call( selector_arg, __VA_ARG__ ) // If the function does not take the arugment as a parameter: #define function_generic_example_direct_type( selector_arg ) _Generic( \ @@ -124,15 +123,15 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; if_generic_selector_defined_include_slot( GENERIC_SLOT_2__function_sig ) \ /* ... */ \ if_generic_selector_defined_include_slot(GENERIC_SLOT_N__function_sig ) \ default: assert_generic_sel_fail \ ) generic_call(selector_arg) #ifndef type_to_expression // Used to keep the _Generic keyword happy as bare types are not considered "expressions" #define type_to_expression(type) (* (type*)NULL) // Instead of using this macro, it should be directly expanded by code generation. #endif // _Generic also suffers from type compability flatting distinctions between typedef by resolving the selection to the underling type and qualifier. // To resolve this these distinctions must be enforce by keeping "compatible" types in separate _Generic expressions: @@ -161,13 +160,15 @@ _Generic_L2((expr), \ default: assert_generic_sel_fail \ ), \ ) generic_call(expr) // Removing example definitions #undef example_with #undef example_with__l2 #undef example_with_generic_layers #undef function_generic_example #undef GENERIC_SLOT_1__example_hash #undef GENERIC_SLOT_2__example_hash #undef generic_example_hash #undef function_generic_example_varadic #undef function_generic_example_direct_type #undef generic_example_do_something_with -
Ed94 revised this gist
Feb 12, 2025 . 1 changed file with 28 additions and 0 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -133,6 +133,34 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; #define type_to_expression(type) (* (type*)NULL) #endif // Instead of using this macro, it should be directly expanded by code generation. // _Generic also suffers from type compability flatting distinctions between typedef by resolving the selection to the underling type and qualifier. // To resolve this these distinctions must be enforce by keeping "compatible" types in separate _Generic expressions: #define example_with__l2(expr) _Generic( \ (expr), \ S64 : example_with_s64, \ default: assert_generic_sel_fail \ ) #define example_with(expr) \ _Generic((expr), \ SSIZE : example_with_SSIZEZ \ default : example_with_not_SSIZE(allocator, in) \ ) generic_call(allocator, in) // This can be made more concise with he following "layer" indicating _Generic macros #define _Generic_L2(expr, ...) default: _Generic(expr, __VA_ARGS__) #define _Generic_L3(expr, ...) default: _Generic(expr, __VA_ARGS__) #define example_with_generic_layers(expr) \ _Generic( (expr), \ S64 : example_with_s64, \ _Generic_L2((expr), \ SSIZE: example_with_SSIZZE \ default: assert_generic_sel_fail \ ), \ ) generic_call(expr) // Removing example definitions #undef function_generic_example -
Ed94 revised this gist
Feb 12, 2025 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -17,7 +17,9 @@ // -------------------------------------------------------------------------------------------------------------------------------------------- // For explanation of intended usage with staged metaprogramming see: https://github.com/Ed94/gencpp/tree/main/gen_c_library#macro-usage // Techncially this can be used for more than just implementing function overloading. // Additional info: // https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/ // https://medium.com/@pauljlucas/generic-in-c-d7ab47e3b5ab // -------------------------------------------------------------------------------------------------------------------------------------------- #ifndef COMMA_OPERATOR -
Ed94 revised this gist
Feb 12, 2025 . 1 changed file with 1 addition and 33 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -131,39 +131,7 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; #define type_to_expression(type) (* (type*)NULL) #endif // Instead of using this macro, it should be directly expanded by code generation. // Removing example definitions #undef function_generic_example #undef GENERIC_SLOT_1__example_hash -
Ed94 revised this gist
Feb 10, 2025 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -138,13 +138,13 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; #ifndef distinct_register_selector // Will define the metadata struct for generic selection usage with the distinct_lookup function macro // Generally does not need to be used unless getting an error similar to: "_Generic association compatible with previous association type" #define distinct_register_selector(type) typedef struct { type* UNUSED__; } Distinct_Typedef_ ## type #endif #ifndef distinct_lookup // This is used by a generic selector to lookup a unique struct typeid of a typedef if distinct_register_selector function macro was utilized // Only necessary to use with _Generic if getting an error similar to: "_Generic association compatible with previous association type" #define distinct_lookup(type) Distinct_Typedef_ ## type #endif // Example: ------------------------------------------------------------------------------------------------------------------------- -
Ed94 revised this gist
Feb 9, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -149,7 +149,7 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; // Example: ------------------------------------------------------------------------------------------------------------------------- // Now this can work so long as typedef_generic_selector was used on the S64 && SSIZE typedefs #define do_something_with(selector_arg) _Generic( \ (selector_arg), \ distinct_lookup(S64) : do_something_with_s64, default: assert_generic_selection_fail, \ distinct_lookup(SSIZE): do_something_with_ssize, default: assert_generic_selection_fail, \ -
Ed94 revised this gist
Feb 9, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -132,7 +132,7 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; #endif // Instead of using this macro, it should be directly expanded by code generation. // _Generic also suffers from type compatability flatting distinctions between typedef by resolving the selection to the underling type and qualifiers are ignored. // To resolve this these distinctions must be enforced using structs that enforce the typedef #ifndef distinct_register_selector -
Ed94 revised this gist
Feb 9, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -132,7 +132,7 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; #endif // Instead of using this macro, it should be directly expanded by code generation. // _Generic also suffers from type compatability flatting distinctions between typedef by resolving the selection to the underling type and qualifier. // To resolve this these distinctions must be enforced using structs that enforce the typedef #ifndef distinct_register_selector -
Ed94 revised this gist
Feb 9, 2025 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -56,7 +56,7 @@ struct UNRESOLVED_GENERIC_SELECTION { void* _THE_VOID_SLOT_; }; UNRESOLVED_GENERIC_SELECTION const assert_generic_selection_fail = {0}; // Which will provide the message: error: called object type 'struct UNRESOLVED_GENERIC_SELECTION' is not a function or function pointer // ---------------------------------------------------------------------------------------------------------------------------------- // Below are generated on demand for an overlaod depdendent on a type: @@ -71,7 +71,7 @@ UNRESOLVED_GENERIC_SELECTION const assert_generic_selection_fail = {0}; // ---------------------------------------------------------------------------------------------------------------------------------- // Then each definiton of a function has an associated define: // #define GENERIC_SLOT_<#>_<generic identifier> <typename>, <function_to_resolve> // Then somehwere later on // <etc> <return_type> <function_id> ( <arguments> ) { <implementation> } -
Ed94 revised this gist
Feb 9, 2025 . No changes.There are no files selected for viewing
-
Ed94 revised this gist
Feb 9, 2025 . 1 changed file with 3 additions and 2 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -15,8 +15,9 @@ // https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md {___/ // It was choosen over the more novel implementations to keep the macros as easy to understand and unobfuscated as possible. // -------------------------------------------------------------------------------------------------------------------------------------------- // For explanation of intended usage with staged metaprogramming see: https://github.com/Ed94/gencpp/tree/main/gen_c_library#macro-usage // Techncially this can be used for more than just implementing function overloading. // Additional info: https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/ // -------------------------------------------------------------------------------------------------------------------------------------------- #ifndef COMMA_OPERATOR -
Ed94 revised this gist
Feb 9, 2025 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -170,4 +170,5 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; #undef hash_example #undef function_generic_example_varadic #undef function_generic_example_direct_type #undef do_something_with #pragma endregion _Generic Macros -
Ed94 revised this gist
Feb 9, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -129,7 +129,7 @@ size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; // Used to keep the _Generic keyword happy as bare types are not considered "expressions" #define type_to_expression(type) (* (type*)NULL) #endif // Instead of using this macro, it should be directly expanded by code generation. // _Generic also suffers from type compability flatting distinctions between typedef by resolving the selection to the underling type and qualifier. // To resolve this these distinctions must be enforced using structs that enforce the typedef -
Ed94 created this gist
Feb 9, 2025 .There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,173 @@ #ifdef INTELLISENSE_DIRECTIVES # pragma once // NOTE(Ed): For C++ generation, this file will not be injected, any macros that are used will either be injected as transparent defines // or have their usage removed during the library generation pass. #endif #pragma region _Generic Macros // ____ _ ______ _ _ ____ _ __ _ // / ___} (_) | ____} | | (_) / __ \ | | | |(_) // | | ___ ___ _ __ ___ _ __ _ ___ | |__ _ _ _ __ ___| |_ _ ___ _ __ | | | |_ _____ _ __ | | ___ __ _ __| | _ _ __ __ _ // | |{__ |/ _ \ '_ \ / _ \ '__} |/ __| | __} | | | '_ \ / __} __} |/ _ \| '_ \ | | | \ \ / / _ \ '_ }| |/ _ \ / _` |/ _` || | '_ \ / _` | // | |__j | __/ | | | __/ | | | (__ | | | |_| | | | | (__| l_| | (_) | | | | | l__| |\ V / __/ | | | (_) | (_| | (_| || | | | | (_| | // \____/ \___}_l l_l\___}_l l_l\___| l_l \__,_l_l l_l\___}\__}_l\___/l_l l_l \____/ \_/ \___}_l l_l\___/ \__,_l\__,_l|_|_| |_|\__, | // 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 {___/ // It was choosen over the more novel implementations to keep the macros as easy to understand and unobfuscated as possible. // -------------------------------------------------------------------------------------------------------------------------------------------- // NOTE: For explanation of intended usage with staged metaprogramming see: https://github.com/Ed94/gencpp/tree/main/gen_c_library#macro-usage // NOTE: Techncially this can be used for more than just implementing function overloading... but thats the of this header at least. // -------------------------------------------------------------------------------------------------------------------------------------------- #ifndef COMMA_OPERATOR #define 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. #endif // Helper macros for argument selection #ifndef select_arg_1 #define select_arg_1( _1, ... ) _1 // <-- Of all th args passed pick _1. #define select_arg_2( _1, _2, ... ) _2 // <-- Of all the args passed pick _2. #define select_arg_3( _1, _2, _3, ... ) _3 // etc.. #define generic_sel_entry_type select_arg_1 // Use the arg expansion macro to select arg 1 which should have the type. #define generic_sel_entry_function select_arg_2 // Use the arg expansion macro to select arg 2 which should have the function. #define generic_sel_entry_comma_delimiter select_arg_3 // Use the arg expansion macro to select arg 3 which should have the comma delimiter ','. #endif #ifndef resolved_function_call #define resolved_function_call // Just used to indicate where the call "occurs" #endif // ---------------------------------------------------------------------------------------------------------------------------------- #ifndef if_generic_selector_defined_include_slot // if_generic_selector_defined_include_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 generic_sel_entry_comma_delimiter is specifically looking for that <comma> , #define if_generic_selector_defined_include_slot( slot_exp ) generic_sel_entry_comma_delimiter( slot_exp, generic_sel_entry_type( slot_exp, ): generic_sel_entry_function( slot_exp, ) 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. #endif // For the occastion where an expression didn't resolve to a selection option the "default: <value>" will be set to: typedef struct UNRESOLVED_GENERIC_SELECTION UNRESOLVED_GENERIC_SELECTION; struct UNRESOLVED_GENERIC_SELECTION { void* _THE_VOID_SLOT_; }; UNRESOLVED_GENERIC_SELECTION const assert_generic_selection_fail = {0}; // Which will provide the message: error: called object type 'struct NO_RESOLVED_GENERIC_SELECTION' is not a function or function pointer // ---------------------------------------------------------------------------------------------------------------------------------- // Below are generated on demand for an overlaod depdendent on a type: // ---------------------------------------------------------------------------------------------------------------------------------- #define function_generic_example( selector_arg ) _Generic( \ (selector_arg), /* Select Via Expression*/ \ /* Extendibility slots: */ \ if_generic_selector_defined_include_slot( GENERIC_SLOT_1__function_sig ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_2__function_sig ) \ default: assert_generic_selection_fail \ ) resolved_function_call( selector_arg ) // ---------------------------------------------------------------------------------------------------------------------------------- // Then each definiton of a function has an associated define: #// #define GENERIC_SLOT_<#>_<generic identifier> <typename>, <function_to_resolve> // Then somehwere later on // <etc> <return_type> <function_id> ( <arguments> ) { <implementation> } // Concrete example: // To add support for long: #define GENERIC_SLOT_1__example_hash long, example_hash__P_long size_t example_hash__P_long( long val ) { return val * 2654435761ull; } // To add support for long long: #define GENERIC_SLOT_2__example_hash long long, example_hash__P_long_long size_t example_hash__P_long_long( long long val ) { return val * 2654435761ull; } // If using an Editor with support for syntax hightlighting macros: // GENERIC_SLOT_1__example_hash and GENERIC_SLOT_2__example_hash should show color highlighting indicating the slot is enabled, // or, "defined" for usage during the compilation pass that handles the _Generic instrinsic. #define hash_example( function_arguments ) _Generic( \ (function_arguments), /* Select Via Expression*/ \ /* Extendibility slots: */ \ if_generic_selector_defined_include_slot( GENERIC_SLOT_1__example_hash ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_2__example_hash ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_3__example_hash ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_4__example_hash ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_5__example_hash ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_6__example_hash ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_7__example_hash ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_8__example_hash ) \ default: assert_generic_selection_fail \ ) resolved_function_call( function_arguments ) // Additional Variations: // If the function takes more than one argument the following is used: #define function_generic_example_varadic( selector_arg, ... ) _Generic( \ (selector_arg), \ if_generic_selector_defined_include_slot( GENERIC_SLOT_1__function_sig ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_2__function_sig ) \ /* ... */ \ if_generic_selector_defined_include_slot(GENERIC_SLOT_N__function_sig ) \ default: assert_generic_selection_fail \ ) resolved_function_call( selector_arg, __VA_ARG__ ) // If the function does not take the arugment as a parameter: #define function_generic_example_direct_type( selector_arg ) _Generic( \ ( type_to_expression(selector_arg) ), \ if_generic_selector_defined_include_slot( GENERIC_SLOT_1__function_sig ) \ if_generic_selector_defined_include_slot( GENERIC_SLOT_2__function_sig ) \ /* ... */ \ if_generic_selector_defined_include_slot(GENERIC_SLOT_N__function_sig ) \ default: assert_generic_selection_fail \ ) resolved_function_call() #ifndef type_to_expression // Used to keep the _Generic keyword happy as bare types are not considered "expressions" #define type_to_expression(type) (* (type*)NULL) #endif // Instead of using this macro, you'll see it directly expanded by the code generation. // _Generic also suffers from type compability flatting distinctions between typedef by resolving the selection to the underling type and qualifier. // To resolve this these distinctions must be enforced using structs that enforce the typedef #ifndef distinct_register_selector // Will define the metadata struct for generic selection usage with the distinct_lookup function macro // Generally does not need to be used unless getting an error similar to: "_Generic association compatible with previous association type" #define distinct_register_selector(type) typedef struct { type* UNUSED__; } Generic_Enforce__ ## type #endif #ifndef distinct_lookup // This is used by a generic selector to lookup a unique struct typeid of a typedef if distinct_register_selector function macro was utilized // Only necessary to use with _Generic if getting an error similar to: "_Generic association compatible with previous association type" #define distinct_lookup(type) Generic_Enforce__ ## type #endif // Example: ------------------------------------------------------------------------------------------------------------------------- // Now this can work so long as typedef_generic_selector was used on the S64 && SSIZE typedefs #define do_something_with(selector_arg, in) _Generic( \ (selector_arg), \ distinct_lookup(S64) : do_something_with_s64, default: assert_generic_selection_fail, \ distinct_lookup(SSIZE): do_something_with_ssize, default: assert_generic_selection_fail, \ default : assert_generic_selection_fail \ ) resolved_function_call(selector_arg) // ---------------------------------------------------------------------------------------------------------------------------------- #ifndef distinct // Can inlay with typedef and a distinct_register_selector. Usage: typedef distinct(int, SomeType); // Generally does not need to be used unless getting an error similar to: "_Generic association compatible with previous association type" // Use distinct_lookup, to resolve the distinct type for the generic selection entry. #define distinct(underlying_type, type) underlying_type type; distinct_register_selector(type) #endif // Removing example definitions #undef function_generic_example #undef GENERIC_SLOT_1__example_hash #undef GENERIC_SLOT_2__example_hash #undef hash_example #undef function_generic_example_varadic #undef function_generic_example_direct_type #pragma endregion _Generic Macros