Why is Standard_CString.hxx included in my attempt at a C++ 17 build?

Hi everyone,

I'm new to OCCT. I'm trying to build some C++ code against OCCT libraries. In my code, I have just added one OCCT include file, for testing, like this:

#include <STEPControl_Reader.hxx>

The build fails due to
/usr/local/include/opencascade/Standard_CString.hxx:61:23: error: ambiguating new declaration of 'int Printf(const char*, ...)'

The full error message is pasted below. I'm wondering why/how my C++ 17 compiler is trying to parse CString classes, and if there is a way to maybe switch this off in cmake. Thanks for any thoughts.

Penny

In file included from /usr/local/include/opencascade/Standard_PrimitiveTypes.hxx:28,
from /usr/local/include/opencascade/Standard_Transient.hxx:20,
from /usr/local/include/opencascade/Standard_Handle.hxx:19,
from /usr/local/include/opencascade/STEPControl_Reader.hxx:22,
from /tmp_cuore_dir/agata/geometry/include/AgataRealisticMuonVeto.hh:8,
from /tmp_cuore_dir/agata/geometry/src/AgataDetectorConstruction.cc:3:
/usr/local/include/opencascade/Standard_CString.hxx:61:23: error: ambiguating new declaration of 'int Printf(const char*, ...)'
61 | Standard_EXPORT int Printf(const char* theFormat, ...);
| ^~~~~~
In file included from /usr/local/root/include/TNamed.h:26,
from /usr/local/root/include/TDictionary.h:44,
from /usr/local/root/include/TClass.h:23,
from /usr/local/root/include/TTree.h:36,
from /tmp_cuore_dir/agata/include/AgataConfigurator.hh:9,
from /tmp_cuore_dir/agata/include/AgataSD.hh:6,
from /tmp_cuore_dir/agata/geometry/include/AgataDetectorConstruction.hh:8,
from /tmp_cuore_dir/agata/geometry/src/AgataDetectorConstruction.cc:1:
/usr/local/root/include/TString.h:495:14: note: old declaration 'void Printf(const char*, ...)'
495 | extern void Printf(const char *fmt, ...) // format and print
| ^~~~~~

gkv311 n's picture

Unfortunately you are facing a collision within global namespace between OCCT and some other framework (ROOT?) both defining Printf() function with the same syntax.

OCCT Standard_CString.hxx:

//! Equivalent of standard C function printf() that always uses C locale
Standard_EXPORT int Printf (const char* theFormat, ...);

ROOT TString.hxx:

extern void  Printf(const char *fmt, ...)    // format and print
#if defined(__GNUC__)
__attribute__((format(printf, 1, 2)))
#endif
;

The header Standard_CString.hxx is massively included by common headers in OCCT, so that it is practically impossible to avoid including it while including OCCT headers (although you may try hacks like #define _Standard_CString_HeaderFile before including OCCT headers to see if it can survive).

OCCT defines a small set of short-named global functions without extra namespace like Printf(), Abs(), Cos() for historical reasons, and it is difficult to get rid of them without patching OCCT and breaking API compatibility with old code.

I may expect that TString.hxx is also massively included by ROOT headers, so that avoid to include this specific header might be close to impossible.

In such cases, the only reliable workaround is to separate code so that to avoid including both frameworks into the same .cpp file. Though in your case this might be painful if you would like to use both frameworks intensively and separation of GUI and Algorithmic parts with common glue neutral layer.

Penny Slocum's picture

Hi, and thank you very much! The code does also rely heavily on ROOT. I did try adding `#define _Standard_CString_HeaderFile` before including the OCCT header, and then the build completed without the error. I will see how far I can get with the co-build, and also consider separating the code like you suggest. Many thanks for the information. -Penny