Is it safe to use #ifdef guards on C++ class member functions?
In practice (look at the generated assembler code using GCC as g++ -O2 -fverbose-asm -S
) what you propose to do is safe. In theory it should not be.
However, there is another practical approach (used in Qt and FLTK). Use some naming conventions in your "hidden" methods (e.g. document that all of them should have dontuse
in their name like int dontuseme(void)
), and write your GCC plugin to warn against them at compile time. Or just use some clever grep(1) in your build process (e.g. in your Makefile
)
Alternatively, your GCC plugin may implement new #pragma
-s or function attributes, and could warn against misuse of such functions.
Of course, you can also use (cleverly) private:
and most importantly, generate C++ code (with a generator like SWIG) in your build procedure.
So practically speaking, your #ifdef
guards may be useless. And I am not sure they make the C++ code more readable.
If performance matters (with GCC), use the -flto -O2
flags at both compile and link time.
See also GNU autoconf -which uses similar preprocessor based approaches.
Or use some other preprocessor or C++ code generator (GNU m4, GPP, your own one made with ANTLR or GNU bison) to generate some C++ code. Like Qt does with its moc
.
So my opinion is that what you want to do is useless. Your unstated goals can be achieved in many other ways. For example, generating "random" looking C++ identifiers (or C identifiers, or ObjectiveC++ names, etc....) like _5yQcFbU0s
(this is done in RefPerSys) - the accidental collision of names is then very improbable.
In a comment you state:
Otherwise, I have to use void* for all Objective-C types in the header, but this way I am losing strong typing
No, you can generate some inline
C++ functions (that would use reinterpret_cast
) to gain again that strong typing. Qt does so! FLTK or FOX or GTKmm also generate C++ code (since GUI code is easy to generate).
My idea was to guard methods with Objective-C types with OBJC macro
This make perfect sense if you generate some C++ or C or Objective C code with these macros.
I suspect if member function pointers or virtual functions are used this will most likely break.
In practice, it won't break if you generate random looking C++ identifiers. Or just if you document naming conventions (like GNU bison or ANTLR does) in generated C++ code (or in generated Objective C++, or in generated C, ... code)
Please notice that compilers like GCC use today (in 2021, internally) several C++ code generators. So generating C++ code is a common practice. In practice, the risks of name collisions are small if you take care of generating "random" identifiers (you could store them in some sqlite database at build time).
also ugly static casts must be added all over the code
These casts don't matter if the ugly code is generated.
As examples, RPCGEN and SWIG -or Bisoncpp- generate ugly C and C++ code which works very well (and perhaps also some proprietary ASN.1 or JSON or HTTP or SMTP or XML related in-house code generators).
The header file is included in both pure C++ and Objective C++ translation units.
An alternative approach is to generate two different header files...
one for C++, and another for Objective C++. The SWIG tool could be inspirational. Of course your (C or C++ or Objective C) code generators would emit random looking identifiers.... Like I do in both Bismon (generating random looking C names like moduleinit_9oXtCgAbkqv_4y1xhhF5Nhz_BM
) and RefPerSys (generating random looking C++ names like rpsapply_61pgHb5KRq600RLnKD
...); in both systems accidental name collision is very improbable.
Of course, in principle, using #ifdef
guards is not safe, as explained in this answer.
PS. A few years ago I did work on GCC MELT which generated millions of lines of C++ code for some old versions of the GCC compiler. Today -in 2021- you practically could use asmjit or libgccjit to generate machine code more directly. Partial evaluation is then a good conceptual framework.
X
defined (or not). Since ensuring that is quite a task, I wouldn't call it safe at all. – Adiaphorismprivate:
not do it? Whom you are hiding them from, as anybody that has the . File can read it? – WartyX
is defined in exactly the same way in all compilation units. It breaches the one definition rule, so the behaviour of your program is undefined. Under the one definition rule, class definitions seen by all compilation units must be identical (in terms of the set of tokens that, collectively, form the class definition). Having one version of a class with declarations of its member functions and one version without breaks that rule. – Neotenyvirtual
function is inside the#ifdef
/#endif
block. You may find duplicate definitions of the virtual function table with different indexes. – Mediator