1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
#ifndef DUTHOMHAS_C_DEFAULT_ARGUMENTS_H
#define DUTHOMHAS_C_DEFAULT_ARGUMENTS_H
// Copyright 2021 Michael Thomas Greer
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt )
// This is a VERY simple library to provide default argument capabilities to C functions.
// I suppose it is possible to dive very much deeper down the preprocessor rabbit hole
// and make using this really short and pretty, but the cost is enormous and this suffices
// me. Example usage:
//
// #include <duthomhas/c-default-args.h>
//
// int my_function( int a, int b, int c );
// #define my_function(...) DUTHOMHAS_CALL_OVERLOAD(my_function_,__VA_ARGS__)
// #define my_function_0() my_function( -7, 512, 42 )
// #define my_function_1(a) my_function( a, 512, 42 )
// #define my_function_2(a,b) my_function( a, b, 42 )
// #define my_function_3(a,b,c) my_function( a, b, c )
//
// int x = my_function(); // same as: int x = my_function( -7, 512, 42 );
// int y = my_function( 15, 4000 ); // same as: int y = my_function( 15, 4000, 42 );
//
// The equivalent construct in C++ would be:
//
// int my_function( int a=-7, int b=512, int c=42 );
//
// Do not define my_function_N for the argument lists that are not permitted and let the
// compiler complain for you if the user did not provide a sufficiently large number of arguments.
//
// #define my_function(...) DUTHOMHAS_CALL_OVERLOAD(my_function_,__VA_ARGS__)
// #define my_function_1(a) my_function( a, M_PI, 74 )
// #define my_function_3(a,b,c) my_function( a, b, c )
//
// int x = my_function(); // compile error
// int y = my_function( 3 ); // OK
// int y = my_function( 3, 5 ); // compile error
// int z = my_function( 3, 5, 7 ); // OK
//
// And, naturally, providing too many arguments will lead to compiler error as well.
//
// int q = my_function( 1, 2, 3, 4, 5 ); // compiler error
//
// The compile error will look something like:
//
// "implicit declaration of function 'my_function_0' is invalid"
// "unresolved external symbol my_function_0 referenced in function main"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif
// Francesco Pretto (ceztko) --> https://stackoverflow.com/a/26685339/2706707
#ifdef _MSC_VER // Microsoft compilers
#define DUTHOMHAS_EXPAND(x) x
#define DUTHOMHAS_NARGS_0(_1, _2, _3, _4, _5, VAL, ...) VAL
#define DUTHOMHAS_NARGS_1(...) DUTHOMHAS_EXPAND(DUTHOMHAS_NARGS_0(__VA_ARGS__, 4, 3, 2, 1, 0))
#define DUTHOMHAS_AUGMENTER(...) unused, __VA_ARGS__
#define DUTHOMHAS_NARGS(...) DUTHOMHAS_NARGS_1(DUTHOMHAS_AUGMENTER(__VA_ARGS__))
#else // Others
#define DUTHOMHAS_NARGS(...) DUTHOMHAS_NARGS_0(0, ## __VA_ARGS__, 5,4,3,2,1,0)
#define DUTHOMHAS_NARGS_0(_0,_1,_2,_3,_4,_5,N,...) N
#endif
// Braden Steffaniak --> https://stackoverflow.com/a/24028231/2706707
#define DUTHOMHAS_GLUE(x, y) x y
#define DUTHOMHAS_OVERLOAD_MACRO2(name, count) name##count
#define DUTHOMHAS_OVERLOAD_MACRO1(name, count) DUTHOMHAS_OVERLOAD_MACRO2(name, count)
#define DUTHOMHAS_OVERLOAD_MACRO(name, count) DUTHOMHAS_OVERLOAD_MACRO1(name, count)
#define DUTHOMHAS_CALL_OVERLOAD(name, ...) DUTHOMHAS_GLUE(DUTHOMHAS_OVERLOAD_MACRO(name, DUTHOMHAS_NARGS(__VA_ARGS__)), (__VA_ARGS__))
#endif
|