This is a big question, so let me clean up a few things:
- We will not ignore the fact that some C ++ functions cannot be implemented in C (for example, support for preliminary basic initialization for any global static object that is linked in).
- This is a thought experiment about what is theoretically possible. Please do not write to say how strong it will be (I know), or what I should do X instead. This is not a practical question, this is a fun theoretical one. :)
The question arises: is it theoretically possible to compile C ++ or C99 on C89, which is as portable as the source code?
Cfront and Comeau C / C ++ will already compile C ++ for C. But for the Comeau C they manufacture are not portable, according to Comeau sales staff. I myself have not used the Comeau compiler, but I assume that the reasons for this are:
- Macros, such as INT_MAX, offsetof (), etc., have already been extended, and their expansion is platform dependent.
- Conditional compilation, such as
#ifdef , is already allowed.
My question is whether these issues can be overcome in a durable way. In other words, can an excellent C ++ to C compiler be written (modulo unsupported C ++ functions)?
The trick is that you need to expand the macros to do a strong parsing, but then collapse them back into their unexpanded forms (so they are again portable and platform independent). But are there any cases when this is fundamentally impossible?
It would be very difficult to categorically say “yes, it’s possible”, but I’m very interested to see some specific counterexamples: code fragments that cannot be compiled in this way for some serious reason. I'm interested in counterexamples C ++ and C99.
I will start with a rough example to emphasize what, in my opinion, a counterexample may look like.
#ifdef __SSE__ #define OP < #else #define OP > #endif class Foo { public: bool operator <(const Foo& other) { return true; } bool operator >(const Foo& other) { return false; } }; bool f() { return Foo() OP Foo(); }
This is difficult because the value of OP and therefore the method call that is generated here is platform dependent. But it looks like the compiler could recognize that the operator syntax tree is dependent on the value of the macro and extends the capabilities of the macro like something like:
bool f() { #if __SSE__ return Foo_operator_lessthan(...); #else return Foo_operator_greaterthan(...); #endif }