Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: What if pre-processor was moved to parser? Date: Thu, 16 Feb 2017 15:46:07 -0800 Organization: None to speak of Lines: 67 Message-ID: References: <11c906d6-9be0-44df-82b4-157fdba3b91c@googlegroups.com> <436a6e24-df32-45d9-b24e-c1e135c32c24@googlegroups.com> <8b49e198-86a5-45b4-ade7-a27ecb4f5e07@googlegroups.com> <7cc856f7-997e-496d-8ebf-ba413cb89d75@googlegroups.com> <7dc5b761-29bb-4244-aa99-ed20cbfa5fcd@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx02.eternal-september.org; posting-host="3490c05baafeea877b77d6bc7baf0dff"; logging-data="27355"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19RGHaD4wKfMg+w60U4lzR1" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:z6WbmSzxqEtP0nk5kAsO1S/udb4= sha1:ikx+L7TkGzX+nCfcnQkIPqs3clU= Xref: csiph.com comp.lang.c:104046 Andrey Tarasevich writes: > On 2/16/2017 10:38 AM, Keith Thompson wrote: >> supercat@casperkitty.com writes: >> [...] >>> The ability to compile a C program as C++ is only useful if the resulting >>> program will run with known semantics. There are some constructs which >>> have defined behavior in C but have no convenient direct equivalent in C++. >> >> For example? >> >> [...] > > #include > > void foo(void) { printf("foo\n"); } > void bar(int a) { printf("bar %d\n", a); } > void baz(int x, int y) { printf("baz %d %d\n", x, y); }; > > int main() > { > void (*const a[3])() = { foo, bar, baz }; > a[0](); > a[1](42); > a[2](4, 2); > } > > Although, if I remember correctly, C is planning to obsolete the > "flexible" '()' parameter list. Parameter lists using () have be "obsolescent" since C89/C90, and the C99 rationale explicitly warns that they're likely to be removed from a future standard aware of any plans by the committee to actually do so. It is possible to do the equivalent without using old-style function declarations. I won't claim that it's particularly convenient. #include void foo(void) { printf("foo\n"); } void bar(int a) { printf("bar %d\n", a); } void baz(int x, int y) { printf("baz %d %d\n", x, y); } int main(void) { typedef void (func0)(void); typedef void (func1)(int); typedef void (func2)(int, int); func0 *const a[] = { (func0*)foo, (func0*)bar, (func0*)baz }; ((func0*)a[0])(); ((func1*)a[1])(42); ((func2*)a[2])(4, 2); } Some might prefer to define typedefs for function pointer types rather than function types. You could also do the whole thing without typedefs, but IMHO they aid in readability. I used `void()(void)` as a "generic" function type, which happens to match the type of foo(). That might be error-prone in some cases. An alternative is to define an otherwise unused struct type and define your "generic" function type to take or return a value of that type, so that all uses of the generic function type require a pointer cast. -- Keith Thompson (The_Other_Keith) kst-u@mib.org Working, but not speaking, for JetHead Development, Inc. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"