1
votes

I'm getting the following error when attempting to build on CentOS 6.4: The only flags being passed here are -Wall and -std=c++11, using gcc 4.7.2

/usr/local/include/rapidjson/writer.h: In member function ‘void rapidjson::Writer::WriteDouble(double)’: /usr/local/include/rapidjson/writer.h:173:53: error: there are no arguments to ‘_snprintf’ that depend on a template parameter, so a declaration of ‘_snprintf’ must be available [-fpermissive] /usr/local/include/rapidjson/writer.h:173:53: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)

The code in question: (from rapidjson/writer.h)

        void WriteDouble(double d) {
            char buffer[100];
#if _MSC_VER
            int ret = sprintf_s(buffer, sizeof(buffer), "%g", d);
#else
            int ret = snprintf(buffer, sizeof(buffer), "%g", d); //this line is the troublemaker
#endif
            RAPIDJSON_ASSERT(ret >= 1);
            for (int i = 0; i < ret; i++)
                    stream_.Put(buffer[i]);
    }

The top of the writer.h file looks like this:

#ifndef RAPIDJSON_WRITER_H_
#define RAPIDJSON_WRITER_H_

#include "rapidjson.h"
#include "internal/stack.h"
#include "internal/strfunc.h"
#include <cstdio>       // snprintf() or _sprintf_s()
#include <new>          // placement ne

Which led me to this question: cstdio stdio.h namespace.

As I understand the answer to the question above, the inclusion of cstdio should declare the snprintf symbol in the standard namespace. So, I thought to include stdio.h to get the symbol defined in the global namespace. The same compilation error results, regardless if I include cstdio, stdio.h, or both files (which I shouldn't have to do)

My question is two parts: Why is gcc looking for _snprintf and not snprintf? Or am I on the wrong track and is this related to the two-part name lookup that gcc does for template parameter binding? (ala 10.8.2, http://idlebox.net/2009/apidocs/gcc-4.4.1.zip/gcc-4.4.1/gcc_10.html#SEC315)

2
Why are you attempting to use stdio.h for C++ code?devnull
I was trying to get a declaration of _snprintf available, per the error message. I assumed (wrongly) that by including stdio.h, it would declare snprintf in the global namespace and that would resolve this problem. That turned out not to be the case, so the error remains.jdt141
Just curious: did you unzip the sources inside /usr/local?devnull
What version of gcc are you using?devnull
gcc version 4.7.2. The sources are in /usr/local/include/rapidjson.jdt141

2 Answers

0
votes

Are you using the -ansi compile flag?

Using -ansi generally says that you want the headers to expose ONLY the interfaces mentioned in the C89 standard. But C89 did not describe snprintf

0
votes

(Cannot comment yet, so I'm writing this as an answer).

Regarding your second question: It's unlikely this has to do with two-phase name lookup. The error message simply says there's an non-dependent undefined smybol (_snprintf).

Ok, why is that happening? The error message is about _snprintf, not the actually used snprintf in writer.h, so if I had to guess I'd say there's some other code redefining that name via #define snprintf _snprintf before including the STL headers. Is there something like that in your code? If possible, remove it.

Some other things to try: Move the inclusion of writer.h to the top of the file (i.e. before redefinition of snprintf occurs), if possible. If not possible, try to #undef snprintf before including writer.h.

Also, such a redefinition alone leads to a different error on my machine. To clarify this: How is the preprocessor symbol _GLIBCXX_USE_C99 defined on your system?

If this doesn't help, some more information is needed. Could you then post the complete error message (and perhaps a minimal example to reproduce)?