1

So i am in a bit of stand off here and im not sure exactly how to go about proceeding, or if its even fixable...

We use a 3rd party SDK provided by another team, this SDK must be used for our app to function properly.

In this SDK, there are lines like this

#define uint16_t UINT16
#define uint8_t UINT8

The issue is in Boost, more specifically the ASIO/Details/cstdint.hpp file has lines that are

using std::uint16_t
using std::uint8_t

My app wont compile now because its really doing

using std::UINT16
using std::UINT8

And its complaining those types do not exist in std namespace obviously.

These UINT16 and UINT8 defines are used everywhere in the app that is very large, so replacing them is not very feasible, and im not even sure if the SDK would function if i did so.

I can try to #undef all of these defines before including the boost header files? And then redefine them after? Seems silly and i somehow doubt it would even work anyways.

Any advice?

user1024792
  • 553
  • 1
  • 10
  • 23
  • 7
    For starters, submit a bug report to the maintainers of the SDK. (Can you tell us which one it is?) – Keith Thompson Apr 02 '18 at 15:42
  • 1
    @KeithThompson it seems it might have proliferated a bit, see https://stackoverflow.com/a/8374301/85371 - I found it in several github repositories already – sehe Apr 02 '18 at 15:45
  • 6
    _"And then redefine them after"_ - why on earth? Can't you just write standards-conformant C++ code instead? Don't buy into FUD. If `UINT16` is *not* equivalent to `std::uint16_t` then they have larger problems and you shouldn't consider using a library that bad. You might consider using typedefs to "recreate" the same typenames, but I don't see what it buys you (except for ugly types names) – sehe Apr 02 '18 at 15:46
  • What is the SDK defining `UINT16` and `UINT8` as? – 1201ProgramAlarm Apr 02 '18 at 15:54
  • 1
    It **might** help if you change those macros to typedefs. So `#define uint16_t UINT16` becomes `typedef UINT16 uint16_t;` etc. That way you at least have names that respect scopes, so might not be as damaging. Of course, defining macros with the same names as standard types is a horrible idea. – Pete Becker Apr 02 '18 at 15:54
  • @PeteBecker still a bad idea, I know WIN32 uses typedefs like that already and it could cause conflicts. Best choice is to just use the stdlib – Mgetz Apr 02 '18 at 16:02
  • @Mgetz -- yes, best choice is to just use the standard library. Unfortunately, that's **not an option**, because this SDK has its own notion of what those names mean. – Pete Becker Apr 02 '18 at 16:44
  • @sehe It's a very large sdk we use at work that has to support a dozen OS's to support all their customers across the corporation. I assume they do this to have a common type pointing to that OS's version so that you can compile your tool across any OS they support and get the expected behavior. – user1024792 Apr 02 '18 at 17:51
  • 1
    Is there a newer version of the SDK that fixes this bug? If not, you might need to fork the SDK and fix it yourself (and submit the fixes back to the maintainers). – Keith Thompson Apr 02 '18 at 17:53
  • @Keith Thompson it's not a bug, it's on purpose to support multiple os's like that like Solaris that do not use the same type names. In it's ifdef if your in Solaris for example it would define Solaris's types to UINT16 or their equivalent. If I use UINT16 in my app I could compile my tool against windows or Solaris without modification. Very powerful when multiple os support is needed. It is one created by a team at my work, not public. – user1024792 Apr 02 '18 at 18:06
  • @user1024792 granted, declaring cross-platform types that are aliases for underlying platform types is indeed useful, but the SDK should be using `typedef` or `using` statements to declare those types. Using `#define` for that purpose is a serious mistake and should be considered a bug, for exactly the reason you stated in your question. That is what Keith was trying to point out. – Remy Lebeau Apr 02 '18 at 18:22
  • @Remy Lebeau good point, I can only assume there is a reason they don't for some of they support. The ask has been around for over a decade so in sure it's come up but I'll ask. For my own code though I think I can just undef them all and typedef since I'm just doing windows. – user1024792 Apr 02 '18 at 18:37
  • 3
    @user1024792: Those particular names, `uint16_t` and `uint8_t` are defined by the standard library. C introduced the `` header in the 1999 ISO C standard, and C++ adopted them in the 2003 ISO C++ standard. Defining non-standard names like `UINT16` is OK. Redefining standard names like `uint16_t` potentially breaks any C or C++ code that includes ``, ``, ``, or ``. That SDK needs to be updated to be compatible with the current language standards. – Keith Thompson Apr 02 '18 at 19:31
  • @RemyLebeau: No, that wasn't my point (though `typedef` certainly would be better than `#define`). See my previous comment. – Keith Thompson Apr 02 '18 at 19:32
  • 3
    It is a bug if the headers of a library break other code (especially if that _other code_ is just using standard library features in the most correct and safe way possible, i.e. namespace-qualified). It's a bug. Period. – sehe Apr 02 '18 at 21:37
  • Thanks for the help @KeithThompson, i will see what they say when i ask them about it. It is HIGHLY unlikely that they will change anything, as there is probably tens or hundreds of thousands of lines of code that enable hundreds of products, the scope of what such a change would break would likely cost way too much time at this point. So im trying to think of ways i can work around it, if possible. Ive tried to make the boost includes the very first thing our application does, but it does not seem to matter. – user1024792 Apr 03 '18 at 09:48

1 Answers1

9

The issue is in Boost, more specifically the ASIO/Details/cstdint.hpp file has lines that are

That's upside down. The issue is clearly in the headers that redefine perfectly common typenames.

The most viable solution is to not include the SDK headers before you include any boost header, ever.

A patchwork workaround would be to undefine the macros. (Down that path lies madness, if you ask me):

#ifdef uint16_t
     #undef uint16_t
#endif
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Sehe's got good advice, exactly what I've done in the past. Wrap that naughty SDKs header files in a project bridging header file, and as part of that wrapping `#undef` all of the troublesome defines, perhaps by providing namespace bridge SDK inlines or const alternatives. Depending on your toolchain, you may be able to get your tools to generate a dump of all the live macros as the end of a translation unit. The preprocessor is evil. – Eljay Apr 02 '18 at 15:48
  • 3
    @Eljay My preferred plan of attack is to completely replace the headers with my own wrapping interface, thereby just including the "messy code" in separate translation units. There's a slight risk the "messy library" is doing other bad things, so I'd scrutizine it closely for any [Undefined Behaviour](https://en.wikipedia.org/wiki/Undefined_behavior) like redefining things leading to ODR violations – sehe Apr 02 '18 at 15:50
  • @Mgetz ASIO doesn't, strictly speaking, depend on OpenSSL, of course. It uses OpenSSL for TLS. Also, that's just about dependency management which has effectively nothing to nothing to with managing messy include files. – sehe Apr 02 '18 at 16:43
  • @sehe The problem is that our tool uses those defines, so undefing them will break everything? – user1024792 Apr 02 '18 at 17:54