1

I'm using a specific toolchain (the one that comes with the BlackBerry Playbook NDK). I think it's based on GCC 4.4.2. When I try compiling certain libraries with this toolchain, I run into strange issues with what I think is c++ global namespace stuff. For example, I'll get errors like:

'::sprintf' has not been declared

I never get these errors when linking against the GNU c++ standard library. However, the Playbook NDK uses the Dinkumware C++ libs by default and I always have to go through each error and usually add in the C equivalent (stdio.h in this case). For reasons beyond my control, I can't link to the GNU c++ standard library, which doesn't exhibit any of these problems.

If I'm trying to compile a bigger project, I can get hundreds of these errors. Is there a workaround that doesn't involve editing the source? In the above example, the file would usually include "cstdio" as a header, but that declares sprintf under the 'std' namespace. So the only options I have are to include the C header or add the std namespace.

Griwes
  • 8,805
  • 2
  • 43
  • 70
Prismatic
  • 3,338
  • 5
  • 36
  • 59
  • 2
    You should add `` not `stdio.h` – K-ballo Jun 10 '12 at 17:46
  • Sorry, I edited my post to reflect what happens. The source file usually includes cstdio. But it'll throw up an error unless I add the function call under the std namespace. – Prismatic Jun 10 '12 at 17:47
  • 3
    His problem is that `` declares everything under the `std` namespace. He's using `` to get around that, and wanted to know if there was another way. I don't think there is, apart from prefixing everything with `std` or using `using namespace std;`. – Shoaib Jun 10 '12 at 17:48
  • Using the GNU STL doesn't solve this problem. – Ken Bloom Jun 10 '12 at 17:49
  • It does for me. To be clear, I'm trying to port over projects using this specific toolchain. If I try compiling the same projects with my desktop machine, I won't have any issues, it'll just work. But the same project won't compile with the toolchain. Also, if I force the tool chain to use the g++ driver instead of its default qcc one, everything compiles fine. The difference between the two being the qcc driver links against Dinkumware libs and g++ links against the GNU stl. I don't know of any other differences between the two methods. – Prismatic Jun 10 '12 at 17:54

3 Answers3

3

Actually, the C++ standard mandates that all symbols declared in the Standard Library (which include the C Library in the <c....> headers) be accessible in the std:: namespace. It does not forbid them to also appear in the global namespace, and some implementations of the C++ Standard Library such as libstdc++ have chosen to let them there for backward compatibility reasons.

You have several possibilities:

  • you can continue to include the C headers directly (like <stdio.h>) however it is generally discouraged as they may not be C++ aware and might create clashes (1)
  • you can prefix each call, though it may be impractical
  • you can cherry pick the symbols you use: using std::printf; either at the top of the file or within each function
  • you can bluntly put a using namespace std; directive. However you'll be pulling a lot of stuff...

My personal recommendation is to either prefix the call or cherry-pick the most used functions and import them in the global or current namespace.

In terms of a migration, one blunt possibility is to actually "wrap" the standard headers:

// cstdio.hpp

#include <cstdio>

#if defined(_DIRKUMWARE_) // note: you'll have to research the symbol to check
namespace yournamespace {
    using std::printf;
    using std::vptrinf;
} // namespace yournamespace
#endif // defined(_DIRKUMWARE_)

And then have a script replace all occurrences of <stdio.h> and <cstdio> in the code base by <cstdio.hpp> (apart in this file, obviously). This way you can tune this file for each implementation of the standard library, instead of repeating the work arounds in each and every file that includes those functions.

Note (1): the C Standard does not mandate whether the functionality be provided by a function or a macro. Typically, min and max might be macros. The C++ Standard mandates functions, which is why using the C++ headers is normally safer.

Griwes
  • 8,805
  • 2
  • 43
  • 70
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
2

Basically you are stuck in a corner.

As per the C++ Standard:

Including cstdio imports the symbol names in std namespace and possibly in Global namespace.

and

Including stdio.h imports the symbol names in Global namespace and possibly in std namespace.

So if in a particular implementation including cstdio doesn't import the symbols in global namespace then the only option you have is to use the fully qualified name for the std namespace.
This is because the behavior is well defined by the C++ Standard just not so commonly known.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
0

If there are a few common header files that the sources include from, you can just modify those with the inclusions you need.

GCC has a command line option called -include that allows you to force a source file to include a file before the rest of it gets compiled. You could modify your Makefile, or project building script's equivalent, to do the inclusions for you.

// c_includes.h
#include <stdio.h>
#include <stdlib.h>
//...

g++ -include c_includes.h ...
jxh
  • 69,070
  • 8
  • 110
  • 193