I have a template like this:
template.h
----------
// Declare a function "func_type()"
void JOIN(func_, T)(T t) { return; }
#undef T
which I use like this in order to generate the same function for different types:
example.c
---------
#define T int
#include "template.h"
#define T float
#include "template.h"
I would like to have a single func that I can use instead of funct_int, func_float, etc. My problem with _Generic is that it doesn't seem possible to define the association-list dynamically. In practical terms I'd like to have something like this:
#define func(TYPE) _Generic((TYPE), AUTO_GENERATED_LIST)
instead of manually defining every new type like this:
#define func(TYPE) _Generic((TYPE), int: func_int..., float: func_float...)
Here's an example of code that is not working: https://ideone.com/HN7sst
I think what you want to do can be achieved with the dreaded "X macros". Create a list such as
#define SUPPORTED_TYPES(X) \
X(int, "%d") \
X(float, "%f") \
where int is the type and in this case I used printf format specifier as another item. These can be anything that counts as valid pre-processor tokens.
Then you can generate all functions through an evil macro like this:
#define DEFINE_F(type, fmt) \
void f_##type (type param) \
{ printf(fmt "\n", param); }
SUPPORTED_TYPES(DEFINE_F)
This creates functions such as void f_int (int param) { printf("%d\n", param); }. That is, very similar to C++ templates - functions doing the same thing but with different types.
You can then write your _Generic macro like this:
void dummy (void* param){}
#define GENERIC_LIST(type, fmt) type: f_##type,
#define func(x) _Generic((x), SUPPORTED_TYPES(GENERIC_LIST) default: dummy)(x)
Here you define the generic asoc. list with GENERIC_LIST, using the type item but ignoring everything else. So it expands to for example int: f_int,.
A problem with this is the old "trailing comma" problem, we can't write _Generic like _Generic((x), int: f_int,)(x) the comma after f_int would mess up the syntax. I solved this with a default clause calling a dummy function, not ideal... might want to stick an assert inside that function.
Full example:
#include <stdio.h>
#define SUPPORTED_TYPES(X) \
X(int, "%d") \
X(float, "%f") \
#define DEFINE_F(type, fmt) \
void f_##type (type param) \
{ printf(fmt "\n", param); }
SUPPORTED_TYPES(DEFINE_F)
void dummy (void* param){}
#define GENERIC_LIST(type, fmt) type: f_##type,
#define func(x) _Generic((x), SUPPORTED_TYPES(GENERIC_LIST) default: dummy)(x)
int main (void)
{
int a = 1;
float b = 2.0f;
func(a);
func(b);
}
Output:
1
2.000000
This is 100% ISO C, no extensions.
Related
Is there a way to do something like what I was willing to do with this syntax:
#define WRAP_MY_FUNCTION(x){Y} void x(int integer){printf("begin\n"); Y ; printf("end\n");}
So I can have this
WRAP_MY_FUNCTION(Foo){printf("hello world\n");}
which is equivalent to
void Foo(int integer)
{
printf("begin\n");
printf("hello world\n");
printf("end\n");
}
to output
begin
hello world
end
Note: I'd prefer to have function code in brackets so the end-user understands this is a code block.
You could pass in another parameter to the macro to define your print statement.
Something like this:
#define WRAP_MY_FUNCTION(x, Y) void x(int integer){printf("begin\n"); Y; printf("end\n");}
WRAP_MY_FUNCTION(Foo, printf("hello world\n"))
If you'd like to make it more clear to the end user that this is a code block and, as rici pointed out, adding a Variadic macro to fix unprotected commas that might be in your source, you could rewrite your definition to be:
#define WRAP_MY_FUNCTION(x, ...)\
void x(int integer) \
{ \
printf("begin\n"); \
__VA_ARGS__ \
printf("end\n"); \
} \
I was trying to define a general function to take input using _Generic in C, This is what I wrote
#include <stdio.h>
#define readlong(x) scanf("%lld",&x);
#define read(x) scanf("%lld",&x);
#define scan(x) _Generic((x), \
long long: readlong, \
default: read \
)(x)
but when I compile it using gcc test.c -std=C11 on gcc 5.3.0, I get error:
error: 'readlong' undeclared (first use in this function)
You can define your helpers to be functions instead of macros. I modified scan so that it would pass the address to the matched function.
static inline int readlong (long long *x) { return scanf("%lld", x); }
static inline int readshort (short *x) { return scanf("%hd", x); }
static inline int unknown (void) { return 0; }
#define scan(x) _Generic((x), \
long long: readlong, \
short: readshort, \
default: unknown \
)(&x)
readlong
is not the variable that you have declared. In:
#define readlong(x) scanf("%11d",&x);
you added (x). This will not let you use readlong without them.
I am delighted by C11's _Generic mechanism - switching on type is something I miss from C++. It is however proving difficult to compose.
For an example, given functions:
bool write_int(int);
bool write_foo(foo);
bool write_bar(bar);
// bool write_unknown is not implemented
I can then write
#define write(X) _Generic((X), \
int : write_int, \
foo: write_foo, \
bar: write_bar, \
default: write_unknown)(X)
and, provided I don't try to use &write or pass it to a function, I can call write(obj) and, provided obj is an instance of one of those types, all is well.
However, in general foo and bar are entirely unrelated to each other. They are defined in different headers, rarely (but occasionally) used together in a single source file. Where then should the macro expanding to the _Generic be written?
At present, I am accumulating header files called things like write.h, equal.h, copy.h, move.h each of which contains a set of function prototypes and a single _Generic. This is workable, but not brilliant. I don't like the requirement to collect together a list of every type in the program in a single place.
I would like to be able to define type foo in a header file, along with the function write_foo, and somehow have the client code able to call the 'function' write. Default looks like a vector through which this could be achieved.
The closest match I can find on this site is c11 generic adding types which has a partial solution, but it's not quite enough for me to see how to combine the various macros.
Let's say that, somewhere in a header file that defines write_bar, we have an existing macro definition:
#define write(x) _Generic((x), bar: write_bar, default: some_magic_here)(x)
Or we could omit the trailing (x)
#define write_impl(x) _Generic((x), bar: write_bar, default: some_magic_here)
Further down in this header, I would like a version of write() that handles either foo or bar. I think it needs to call the existing macro in its default case, but I don't believe the preprocessor is able to rename the existing write macro. If it were able to, the following could work:
#ifndef WRITE_3
#define WRITE_3(X) write(x)
#undef write(x)
#define write(x) __Generic((x),foo: write_foo,default: WRITE_3)(x)
Having just typed that out I can sort-of see a path forward:
// In bar.h
#ifndef WRITE_1
#define WRITE_1(x) __Generic((x), bar: write_bar)
#elif !defined(WRITE_2)
#define WRITE_2(x) __Generic((x), bar: write_bar)
#elif !defined(WRITE_3)
#define WRITE_3(x) __Generic((x), bar: write_bar)
#endif
// In foo.h
#ifndef WRITE_1
#define WRITE_1(x) __Generic((x), foo: write_foo)
#elif !defined(WRITE_2)
#define WRITE_2(x) __Generic((x), foo: write_foo)
#elif !defined(WRITE_3)
#define WRITE_3(x) __Generic((x), foo: write_foo)
#endif
// In write.h, which unfortunately needs to be included after the other two
// but happily they can be included in either order
#ifdef WRITE_2
#define write(x) WRITE_1(x) WRITE_2(x) (x)
#elif
// etc
#endif
This doesn't actually work though, since I can't find a way to make WRITE_N(x) expand to nothing when x doesn't match the argument list. I see the error
controlling expression type 'struct foo' not compatible with any generic association type
Or
expected expression // attempting to present an empty default clause
I believe to distribute the write() definition between several files | macros I need to work around either of the above. A _Generic clause which reduces to nothing in the default case would work, as would one which reduces to nothing if none of the types match.
Getting yet more hackish, if the functions take a pointer to a struct instead of an instance of one, and I provide write_void(void*x) {(void)x;} as the default option, then the code does compile and run. However, expanding write as
write(x) => write_void(x); write_foo(x); write_void(x);
is clearly pretty bad in itself, plus I don't really want to pass everything by pointer.
So - can anyone see a way to define a single _Generic 'function' incrementally, i.e. without starting with a list of all types it will map over? Thank you.
The need for type-generic functions across multiple, unrelated files suggests that the program design is poor.
Either those files are related and should share a common parent ("abstract base class") where the type-generic macros and function declarations can then be stated.
Or they are unrelated, but share some common method for whatever reason, in which case you need to invent a common, generic abstraction layer interface which they can then implement. You should always consider the program design on a system level the first thing you do.
This answer does not use _Generic, but proposes a different program design entirely.
To take the example from a comment, with bool equal(T lhs, T rhs). That's the latter of the above two cases, a common interface shared by multiple modules. The first thing to observe is that this is a functor, a function which can be used in turn by generic algorithms such as search/sort algorithms. The C standard suggests how functors should preferably be written:
int compare (const void* p1, const void* p2)
This is the format used by standard functions bsearch and qsort. Unless you have good reasons, you shouldn't deviate from that format, because if you don't, you'll get searching & sorting for free. Also, this form has the advantage of doing lesser, greater and equal checks all in the same function.
The classic C way to implement a common interface for such a function in C would be a header containing this macro:
Interface header:
#define compare(type, x, y) (compare_ ## type(x, y))
Module that implements the header:
// int.c
int compare_int (const void* p1, const void* p2)
{
return *(int*)p1 - *(int*)p2;
}
Caller:
if( compare(int, a, b) == 0 )
{
// equal
}
This has the advantage of abstraction: the interface header file doesn't need to know all the types used. The disadvantage is that there is no type safety what-so-ever.
(But this is C, you'll never get 100% type safety through the compiler. Use static analysis if it is a big concern.)
With C11 you can improve type safety somewhat by introducing a _Generic macro. There's a big problem with that though: that macro has to know about all existing types in advance, so you can't put it in an abstract interface header. Rather, it should not be in a common header because then you'll create a tight coupling between every single, unrelated module using that header. You could make such a macro in the calling application, not to define an interface, but to ensure type safety.
What you could do instead, is to enforce an interface through inheritance of an abstract base class:
// interface.h
typedef int compare_t (const void* p1, const void* p2);
typedef struct data_t data_t; // incomplete type
typedef struct
{
compare_t* compare;
data_t* data;
} interface_t;
The module that inherits the interface sets the compare function pointer to point at the specific comparison function, upon object creation. data is private to the module and could be anything. Suppose we create a module called "xy" that inherits the above interface:
//xy.c
struct data_t
{
int x;
int y;
};
static int compare_xy (const void* p1, const void* p2)
{
// compare an xy object in some meaningful way
}
void xy_create (interface_t* inter, int x, int y)
{
inter->data = malloc(sizeof(data_t));
assert(inter->data != NULL);
inter->compare = compare_xy;
inter->data->x = x;
inter->data->y = y;
}
A caller can then work with the generic interface_t and call the compare member. We've achieved polymorphism, as the type-specific compare function will then get called.
Based loosely on Leushenko's answer to multiparameter generics I have come up with the following horrible solution. It requires that the arguments will be passed by pointer, and the boilerplate involved is pretty bad. It does compile and run though, in a fashion which allows functions to return a value.
// foo.h
#ifndef FOO
#define FOO
#include <stdio.h>
#include <stdbool.h>
struct foo
{
int a;
};
static inline int write_foo(struct foo* f)
{
(void)f;
return printf("Writing foo\n");
}
#if !defined(WRITE_1)
#define WRITE_1
#define WRITE_PRED_1(x) _Generic((x), struct foo * : true, default : false)
#define WRITE_CALL_1(x) \
_Generic((x), struct foo * \
: write_foo((struct foo*)x), default \
: write_foo((struct foo*)0))
#elif !defined(WRITE_2)
#define WRITE_2
#define WRITE_PRED_2(x) _Generic((x), struct foo * : true, default : false)
#define WRITE_CALL_2(x) \
_Generic((x), struct foo * \
: write_foo((struct foo*)x), default \
: write_foo((struct foo*)0))
#elif !defined(WRITE_3)
#define WRITE_3
#define WRITE_PRED_3(x) _Generic((x), struct foo * : true, default : false)
#define WRITE_CALL_3(x) \
_Generic((x), struct foo * \
: write_foo((struct foo*)x), default \
: write_foo((struct foo*)0))
#endif
#endif
// bar.h
#ifndef BAR
#define BAR
#include <stdio.h>
#include <stdbool.h>
struct bar
{
int a;
};
static inline int write_bar(struct bar* b)
{
(void)b;
return printf("Writing bar\n");
}
#if !defined(WRITE_1)
#define WRITE_1
#define WRITE_PRED_1(x) _Generic((x), struct bar * : true, default : false)
#define WRITE_CALL_1(x) \
_Generic((x), struct bar * \
: write_bar((struct bar*)x), default \
: write_bar((struct bar*)0))
#elif !defined(WRITE_2)
#define WRITE_2
#define WRITE_PRED_2(x) _Generic((x), struct bar * : true, default : false)
#define WRITE_CALL_2(x) \
_Generic((x), struct bar * \
: write_bar((struct bar*)x), default \
: write_bar((struct bar*)0))
#elif !defined(WRITE_3)
#define WRITE_3
#define WRITE_PRED_3(x) _Generic((x), struct bar * : true, default : false)
#define WRITE_CALL_3(x) \
_Generic((x), struct bar * \
: write_bar((struct bar*)x), default \
: write_bar((struct bar*)0))
#endif
#endif
// write.h
#ifndef WRITE
#define WRITE
#if defined(WRITE_3)
#define write(x) \
WRITE_PRED_1(x) ? WRITE_CALL_1(x) : WRITE_PRED_2(x) ? WRITE_CALL_2(x) \
: WRITE_CALL_3(x)
#elif defined(WRITE_2)
#define write(x) WRITE_PRED_1(x) ? WRITE_CALL_1(x) : WRITE_CALL_2(x)
#elif defined(WRITE_1)
#define write(x) WRITE_CALL_1(x)
#else
#error "Write not defined"
#endif
#endif
// main.c
#include "foo.h"
#include "bar.h"
#include "write.h"
int main()
{
struct foo f;
struct bar b;
int fi = write(&f);
int bi = write(&b);
return fi + bi;
}
I really hope there's a better way than this.
I believe the title is self-explanatory, but here's an example to illustrate what I'm trying to accomplish:
#define PASTE2(_0, _1) _0 ## _1
#define DEFINE_OPS_FOR_TYPE(TYPE) \
int PASTE2(do_something_with_, TYPE)(void) { \
/* do_something_with_<TYPE> */ \
}
Everything works fine for char, int, and single-worded types, but when it
comes to unsigned types, or others that have multiple keywords, using token pasting (a ## b) does not generate a valid name due to the whitespace (e.g.: do_something_with_foo bar).
The easiest solution I could think of is to change the DEFINE_OPS_FOR_TYPE macro
to take a valid name as the 2nd parameter. For example:
#define DEFINE_OPS_FOR_TYPE(TYPE, NAME_FOR_TYPE) \
int PASTE2(do_something_with_, NAME_FOR_TYPE)(void) { \
/* do_something_with_<NAME_FOR_TYPE> */ \
}
This works as expected, but I'm curious about other possible solutions, even if they're overly complex. I thought of using _Generic, but I fail to see how it would help in defining a name.
Can you think of another solution?
On the level of declaration or definition of the symbols that you want to do there is not much way out of typedefing things to a unique identifier for the type in question. _Generic or equivalent replacements kick in too late to be useful for the preprocessor.
But there is only a finite number of standard types that pose such a problem. So you can easily come up with a convention for typedeffing these.
Where _Generic can help is on the usage side of your such defined symbols. Here you can then do something like
_Generic((X),
unsigned long: do_something_with_ulong,
unsigned char: do_something with_uchar,
...
)(X)
In P99 I follow this scheme, and you would find a lot of support macros for it already in place.
I ended up using a macro with an empty argument. Example:
#define STR2(x) # x
#define STR(x) STR2(x)
#define PASTE3(_1,_2,_3) _1 ## _2 ## _3
#define FOO(_1,_2,_3) PASTE3(_1, _2, _3)
printf("%s\n", STR(FOO(int,,)));
printf("%s\n", STR(FOO(unsigned, int,)));
printf("%s\n", STR(FOO(unsigned, long, long)));
As you can see here, the output is:
int
unsignedint
unsignedlonglong
I don't remember whether using empty macro arguments is well defined according to the standard, but I can tell you that Clang 3.1 doesn't emit any warnings for -std=c11 with -pedantic.
Here's some code if you want to try:
#include <stdio.h>
#include <limits.h>
#define PASTE4(_1,_2,_3,_4) _1 ## _2 ## _3 ## _4
#define DEFINE_OPS_FOR_TYPE1(T1) DEFINE_OPS_FOR_TYPE2(T1,)
#define DEFINE_OPS_FOR_TYPE2(T1, T2) DEFINE_OPS_FOR_TYPE3(T1,T2,)
#define DEFINE_OPS_FOR_TYPE3(T1, T2, T3) \
int PASTE4(write_,T1,T2,T3)(FILE *file, void *data) { \
T1 T2 T3 foo; \
int written = fprintf(file, fmt_specifier(foo), *((T1 T2 T3 *)data));\
return written > 0 ? 0 : -1; \
}
#define fmt_specifier(x) \
_Generic((x), \
int: "%i", \
unsigned int: "%u", \
unsigned long long: "%llu", \
default: NULL \
)
DEFINE_OPS_FOR_TYPE1(int)
DEFINE_OPS_FOR_TYPE2(unsigned, int)
DEFINE_OPS_FOR_TYPE3(unsigned, long, long)
int main() {
int var_int = INT_MAX;
write_int(stdout, &var_int);
printf("\n");
unsigned int var_uint = UINT_MAX;
write_unsignedint(stdout, &var_uint);
printf("\n");
unsigned long long var_ullong = ULLONG_MAX;
write_unsignedlonglong(stdout, &var_ullong);
printf("\n");
return 0
}
I would like to do something like the following:
F_BEGIN
F(f1) {some code}
F(f2) {some code}
...
F(fn) {some code}
F_END
and have it generate the following
int f1() {some code}
int f2() {some code}
...
int fn() {some code}
int (*function_table)(void)[] = { f1, f2, ..., fn };
The functions themselves are easy. What I can't seem to do is to keep track of all of the names until the end for the function_table.
I looked at this question and this question but I couldn't get anything to work for me.
Any ideas?
The normal way of doing this with the preprocessor is to define all the functions in a macro that takes another macro as an argument, and then use other macros to extract what you want. For your example:
#define FUNCTION_TABLE(F) \
F(f1, { some code }) \
F(f2, { some code }) \
F(f3, { some code }) \
:
F(f99, { some code }) \
F(f100, { some code })
#define DEFINE_FUNCTIONS(NAME, CODE) int NAME() CODE
#define FUNCTION_NAME_LIST(NAME, CODE) NAME,
FUNCTION_TABLE(DEFINE_FUNCTIONS)
int (*function_table)(void)[] = { FUNCTION_TABLE(FUNCTION_NAME_LIST) };
If you have a C99 complying compiler, the preprocessor has variable length argument lists. P99 has a preprocessor P99_FOR that can do "code unrolling" like the one you want to achieve. To stay close to your example
#define MYFUNC(DUMMY, FN, I) int FN(void) { return I; }
#define GENFUNCS(...) \
P99_FOR(, P99_NARG(__VA_ARGS__), P00_IGN, MYFUNC, __VA_ARGS__) \
int (*function_table)(void)[] = { __VA_ARGS__ }
GENFUNCS(toto, hui, gogo);
would expand to the following (untested)
int toto(void) { return 0; }
int hui(void) { return 1; }
int gogo(void) { return 2; }
int (*function_table)(void)[] = { toto, hui, gogo };
This is sort of abuse of CPP but a common type of abuse. I handle situations
like this by defining dummy macros
#define FUNCTIONS \
foo(a,b,c,d) \
foo(a,b,c,d) \
foo(a,b,c,d)
now,
#define foo(a,b,c,d) \
a+b ;
FUNCTIONS
#undef foo
later, when you want something different done with the same list
#define foo(a,b,c,d) \
a: c+d ;
FUNCTIONS
#undef foo
It's a bit ugly and cumbersome, but it works.
There's this thing called X Macro which is used as:
a technique for reliable maintenance of parallel lists, of code or data, whose corresponding items must appear in the same order
This is how it works:
#include <stdio.h>
//you create macro that contains your values and place them in (yet) not defined macro
#define COLORS\
X(red, 91)\
X(green, 92)\
X(blue, 94)\
//you can name that macro however you like but conventional way is just an "X"
//and then you will be able to define a format for your values in that macro
#define X(name, value) name = value,
typedef enum { COLORS } Color;
#undef X //so you redefine it below
int main(void)
{
#define X(name, value) printf("%d, ", name);
COLORS
#undef X
return 0;
}
Solution for your problem would be:
#define FUNCTIONS \
F(f1, code1)\
F(f2, code2)\
F(f3, code3)
#define F(name, code) int name(void){code}
FUNCTIONS
#undef F
#define F(name, code) &name,
int (*function_table[])(void) = { FUNCTIONS };
#undef F
Boost is a C++ library, but it's Preprocessor module should still be good for use in C. It offers some surprisingly advanced data types and functionality for use in the preprocessor. You could check it out.