Skip to content

Use C++ std headers. Defer to proper isfinite for MSVC and GCC. #218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed

Use C++ std headers. Defer to proper isfinite for MSVC and GCC. #218

wants to merge 4 commits into from

Conversation

connormanning
Copy link
Contributor

This request contains two commits for solving two issues:

  • isfinite compilation error #214, which is only related to compilers besides MSVC/Sun. This fixes the GCC compilation error when cmath has been included in a project prior to building JsonCpp, and unifies the include format with the rest of JsonCpp to prefer the C++ standard headers.
  • @Dani-Hub's fix for correcting the preprocessor logic to make sure isfinite works on certain versions of MSVC.

@connormanning
Copy link
Contributor Author

Copy-paste oversight on my part, sorry. I've now removed the snprintf logic from the unrelated isfinite logic, and incorporated the other change recommended in #214.

@cdunn2001
Copy link
Contributor

I'm fine with this. (And I'll put Dani's name on the 2nd commit before merging.) But let's see if anyone finds any problems anywhere.

@Dani-Hub? Will this work with previous versions of VisualStudio?

@Dani-Hub
Copy link
Contributor

I'm a bit concerned regarding the other header changes to the proper <c***> forms: As far as I see the code now includes <cstring> (for example), but still refers to unqualified snprintf: To make this work, we presumably need the same macro trick as you already did for isfinite. But I can only give a more definitive statement in about three hours from now, when I can test the suggested changes on my system.

@connormanning
Copy link
Contributor Author

This might be a bit too 'out there', but what do you guys think of something like this sample? This removes all the nasty logic from the reader/writer, so lack of compiler support is 100% transparent and implementers can act as if everything exists natively in the std namespace. Specifically look at the diffs of the reader/writer for why I like this solution.

Note that I did change functionality at this point. I wasn't sure why the Visual Studio logic branch did not include the isfinite logic, so I made them all follow the same flow - of course if that was there for a reason, this aspect can be reverted.

I'm not sure if the std::forward or the Args&&... stuff is fully supported everywhere (maybe @Dani-Hub can comment on MSVC support?), but judging by this FAQ entry I hope it would be ok since this is all standard C++11.

@Dani-Hub
Copy link
Contributor

This code wouldn't work for VS 2012, because it currently does not support variadic templates. Furthermore it is very ill-advised to add declarations to namespace std (except for adding explicit or partial specializations of library components if at least one template parameter depends on a user-defined type). It is unfortunately an illusion to emulate a conforming compiler and still referring to namespace std. To realize what you want here it is much simpler to define a (static) function in namespace Json that instead delegates to the right function. For conforming systems this will delegate to the corresponding function from namespace std. Here is a abbreviated sketch:

#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // VC++ 6.0 - 11.0
#include <float.h>
namespace Json
{
 static inline bool isfinite_call(double v)
 {
   return _finite(v);
 }
}
#elif defined(__sun) && defined(__SVR4) // Solaris
#include <ieeefp.h>
namespace Json
{
 static inline bool isfinite_call(double v)
 {
   return finite(v);
 }
}
#else
#include <cmath>
namespace Json
{
 static inline bool isfinite_call(double v)
 {
   return std::isfinite(v);
 }
}
#endif

and then refer to (Json::)isfinite_call within the library.

@connormanning
Copy link
Contributor Author

Ok, never mind the std::forward suggestion - the reason for the std::forward was because std::isfinite has 3 overloads, which would quickly become intrusive (even though currently only one is used by JsonCpp) to handle other future issues like this in the same way if overloads all had to be reimplemented separately.

I've updated the pull request to handle snprintf in the same way that isfinite is handled, so hopefully this one is complete (let me know if VS testing turns up anything needing fixing).

@Dani-Hub
Copy link
Contributor

The new patch looks good to me - thanks! We could still improve it a bit by moving the logic related to _snprintf and sprintf_s to that place, but that presumably exceeds the idea of this request and I will do that anyway during my work on #209.

@cdunn2001 cdunn2001 mentioned this pull request Mar 12, 2015
@cdunn2001 cdunn2001 closed this in 951bd3d Mar 12, 2015
cdunn2001 pushed a commit to cdunn2001/jsoncpp that referenced this pull request Mar 31, 2015
This reverts commit 1c58876.

std::snprintf() is only available in C++11, which is not provided by
all compilers. Since the C library snprintf() can easily be used as a
replacement on Linux systems, this patch changes jsoncpp to use the C
library snprintf() instead of C++11 std::snprintf(), fixing the build error
below:

    src/lib_json/json_writer.cpp:33:18: error: 'snprintf' is not a member of 'std'

See open-source-parsers#231, open-source-parsers#224, and open-source-parsers#218.
This was referenced Mar 31, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants