nlohmann / json

JSON for Modern C++

Home Page:https://json.nlohmann.me

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

json.hpp:5746:32: error: 'to_string' is not a member of 'std'

Ingener74 opened this issue · comments

Hello.
On Android i have this messages

  • json.hpp:5746:32: error: 'to_string' is not a member of 'std'
  • json.hpp:6911:36: error: 'strtold' is not a member of 'std'

android ndk have no to_strign realization

The first one works fine for us, we use the c++-shared library.

We had to add this function to our codebase to handle the second one.
inline long double strtold(const char _nptr, char *_endptr)
{
return strtod(nptr, endptr);
}

Hey @Ingener74, could you please tell me which compiler you are using?

Hello @nlohmann, i am using arm-linux-androideabi-4.9 toolchain for compiling

Could this maybe solve your problem: http://stackoverflow.com/a/27589053 ?

Thanks @nlohmann, i known this solution :) but that about strtold?
I wanted to ask whether it will be added to your library? for android

Ok, I'll have a look at strtold. It would be easier to check on OSX - is there an OSX version of the compiler you use?

On Mac OS X i use compiler

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/c++/4.2.1
Apple LLVM version 7.0.0 (clang-700.0.72)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

but on mac os everythink compiles ok

I meant the compiler to create code for Android. Is there a way to cross-compile from OSX?

You need the android NDK.

Yes, it is available for OS X.

Hello @nlohmann i agree with @gregmarr, you need Android NDK for compiling
https://developer.android.com/ndk/downloads/index.html

Hi,

for a current project I compiled this library with Android NDK r10e, (it includes gcc 4.9) together with gnustl-shared library.
The errors mentioned by @Ingener74 are still in the json-lib, thus I created a small patch-file for that.

On android, it adds the function std::to_string (common workaround implementation, found on stackoverflow) and std::strtold (workaround implementation suggested by @gregmarr).

Hopefully this patch is usefull for anyone who want to use this library on Android. Maybe linking from the main-README to those compatibility patches would be a good idea.

Best regards,
ZG

From 092170941c6a69cbc3a113b098940b4c03b448c2 Mon Sep 17 00:00:00 2001
From: Andre Netzeband <andre@netzeband.eu>
Date: Sat, 28 Nov 2015 13:08:39 +0100
Subject: [PATCH] Added better android support.

Added Android NDK support.
---
 src/json.hpp | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/json.hpp b/src/json.hpp
index 1e3cd11..e878295 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -70,6 +70,25 @@ Class @ref nlohmann::basic_json is a good entry point for the documentation.
     using ssize_t = SSIZE_T;
 #endif

+#ifdef __ANDROID__
+   // Workaround for Android NDK builds (version r10e) that does not support std::to_string and std::strold so far
+   namespace std
+   {
+       template <typename T>
+       std::string to_string(T Value)
+       {
+           std::ostringstream TempStream;
+           TempStream << Value;
+           return TempStream.str();
+       }
+       
+       inline long double strtold(const char * str, char ** str_end)
+       {
+           return strtod(str, str_end);
+       }       
+   }
+#endif
+
 /*!
 @brief namespace for Niels Lohmann
 @see https://github.com/nlohmann
-- 
2.5.0.windows.1

BTW: Unit-Tests are running fine on Android Emulator with these changes.

0001-Added-better-android-support.patch.txt

Thanks! I'm on holiday right now and shall have a look then!

Thanks @ZahlGraf! I added your patch to the code. @Ingener74, can you please check if this fixes your original issue?

Thanks :) In the meanwhile I'm using your lib very successfully on an Android project.

Hi, I just wanted to add that this bug goes a lot deeper than Android; I was getting this issue with a fresh install of MinGW on Windows 10. After chasing proposed changes across the net, I fixed it by manually patching some headers using this:

http://tehsausage.com/mingw-to-string

After these changes, it still wasn't working, but it wasn't because of _GLIBCXX_HAVE_BROKEN_VSWPRINTF, but rather _GLIBCXX_USE_C99, which needed to be defined in os_defines.h. Finally, because I was using stricmp(), I had to switch to using -std=gnu++11 as a compiler option.

I hope this helps someone, because that workaround is terrible ;)

@Ratstail91, what do you propose?

I didn't notice that you'd added the std::to_string overload. I haven't updated our project to use this version yet, but I suspect that this is going to cause problems for us, as the C++ library that we use for Android (c++_shared, from LLVM) already contains that function. Also, it is not allowed for user code to add things to the std namespace except in very specific circumstances. I think that adding std::to_string should be done by the application, not the library, as the reason it's missing is the application's choice of which NDK standard library to use, not an inherent platform limitation. This is analogous to not supporting g++ 4.8.

Hi @gregmarr, I understand. If you experience problems with the current version, please let me know.

@nlohmann I'd recommend not adding std::to_string, partially because of what @gregmarr said. Instead, I'd determine what implementations of C++ that this tool is compatible with, and give some advice for those who are having trouble with it, possibly in a help or README file. I'd be happy to write that up myself, since I've dealt with it.

Worst case scenario, you could write a custom function to_string_ex(), implementing the necessary functionality yourself, but this is not recommended.

nlohmann::to_string is alternative that makes it easy for those with fucked up standard lib implementations and is obvious that it acts similar to std::to_string.

@whackashoe Adding it to namespace nlohmann is an option, but I still don't like it...

I removed the hack for MinGW/Android and added a small section to the README file. Thanks everybody for the discussion!

Hi, I am using the implementation c functions to support in Android ndk, the next function:

    son.hpp:6911:36: error: 'strtold' is not a member of 'std'

The method use in JNI Android

     inline long double strtold(const char * str, char ** str_end)
   {
       return strtod(str, str_end);
  }   

Launch the next error when I compile:

      error: 'strtod' is not a member of 'std'
      return std::strtod(str, str_end);

Hi @fh127, did you have a look at the notes regarding Android in the README file?

I didn't put this in the above, but if you're in Visual Studio for Android:

  • In General, set Platform Toolset to Clang 3.,6, and STL to LLVM libc++ (shared or static).
  • In Language, set C++ Language Standard to C++11 or newer.
  • Add $(VS_NdkRoot)\sources\android\support\include to include directories to work around a VS bug with the LLVM library.
commented

Extended workaround:

#ifdef __ANDROID__
// Workaround for Android NDK builds (version r10e) that does not support std::to_string and std::strold so far
namespace std
{
   template <typename T>
   std::string to_string(T Value)
   {
       std::ostringstream TempStream;
       TempStream << Value;
       return TempStream.str();
   }

   inline long double strtold(const char * str, char ** str_end)
   {
       return strtod(str, str_end);
   }

   int stoi( const std::string& str, std::size_t* pos = 0, int base = 10 )
   {
        const char* begin = str.c_str() ;
        char* end = nullptr ;
        long value = std::strtol( begin, &end, base ) ;

        if( errno == ERANGE || value > std::numeric_limits<int>::max() )
            throw std::out_of_range( "stoi: out ofrange" ) ;

        if( end == str.c_str() )
            throw std::invalid_argument( "stoi: invalid argument" ) ;

        if(pos) *pos = end - begin ;

        return value ;
   }
}
#endif

Problem is 'strtof' is still missing. Where can I find some good implementation of it?
No, I can't use c++_static/_shared - I use cocos2d-x and this causes tons of errors (I have to use gnustl_static).

@piotrros thanks for the input. As I mentioned in #219 (comment), is there a way to get a step-by-step description so I can automatically test for Android NDK? So far, I often got differing explanations in what works and what not, so I want to test myself before adding code to the library.

I would recommend against this library doing the above as a standard part of the code, as it invokes undefined behavior. Providing it as "use at your own risk code in the documentation" is a slightly different story as the user is in full control and won't affect those who don't need it.

It is undefined behavior to add declarations or definitions to namespace std or to any namespace nested within std, with a few exceptions noted below
http://en.cppreference.com/w/cpp/language/extending_std

If the library must add support for this, it should be via a function that is legal to replace:

namespace nlohmann
{
    namespace std_support
    {
        template <typename T>
        std::string to_string(T Value)
        {
#ifdef NLOHMANN_NEEDS_REPLACEMENT_TO_STRING
            std::ostringstream TempStream;
            TempStream << Value;
            return TempStream.str();
#else
            return std::to_string(value);
#endif
        }
    }
}

and then the library code uses std_support::to_string instead of std::to_string. Users whose environment doesn't have std::to_string can then define NLOHMANN_NEEDS_REPLACEMENT_TO_STRING.

@gregmarr I totally agree that the std namespace should not be extended.

In any case, it would be nice to have a reproducible Android environment to experiment.

This is how I worked around the Android issues for one particular configuration. It's nicer than interleaving ifdefs: zewt@0e8acd8

Sorry, I don't have any special instructions for setting up an Android environment--the Android native build situation is such a mess I use Visual Studio to do my native work, but that isn't really what you want for a test environment.

@zewt thanks for the example! Could you please have a look at #219 (comment) and help me find a way to reproduce the issues for the future?

I'd like to bring up that this is not an android-only issue. It is related, I believe, with arm gcc compiler in general.
I'm trying to use this library on the Spark Particle controllers. The code is compiled with arm-none-eabi-gcc -std=gnu++11 ... but yet std::string is not defined.

Some hints:
http://stackoverflow.com/questions/19122574/to-string-isnt-a-member-of-std

Which gcc version are you using?

Von meinem iPhone gesendet

Am 23.05.2016 um 18:08 schrieb Alain Scialoja notifications@github.com:

I'd like to bring up that this is not an android-only issue. It is related, I believe, with arm gcc compiler in general.
I'm trying to use this library on the Spark Particle controllers. The code is compiled with arm-none-eabi-gcc -std=gnu++11 ... but yet std::string is not defined.

Some hints:
http://stackoverflow.com/questions/19122574/to-string-isnt-a-member-of-std


You are receiving this because you modified the open/close state.
Reply to this email directly or view it on GitHub

I'm using gcc11. The issue is with the ARM gcc + newlib toolchain as mentioned in this thread

Never heard of that version. What's the output for --version?

Von meinem iPhone gesendet

Am 23.05.2016 um 19:09 schrieb Alain Scialoja notifications@github.com:

I'm using gcc11. The issue is with the ARM gcc + newlib toolchain as mentioned in this thread


You are receiving this because you modified the open/close state.
Reply to this email directly or view it on GitHub

Sorry, I said something stupid in there. I'm using arm-none-eabi-gcc 4.9 . With Particle.io devices, you can compile and flash the firmware from the cloud too. Not sure if the Spark Particle toolchain still uses 4.8 or 4.9, but I get the same error if I build on the cloud. Here's the particle conversations about the issue.

I checked some more compilers from different NDK versions (see #219). So far, I was not able to reproduce the 'to_string' is not a member of 'std' error.

I do not understand why this is closed. v2.1.1 still does not compile under mingw

I have applied a hack as inspired by @gregmarr so that it does compile. For the convenience of others who hit this, here is the file:

json_hpp_v2_1_1_for_mingw.zip

BTW the hacks suggested by a link in the README are far too complicated and scary, involving slashing at the mingw installation. No thank you!

I do not understand why this is closed. v2.1.1 still does not compile under mingw

This library requires a C++11 compliant compiler and standard library. It's not this library's fault that it doesn't compile under mingw, it's mingw's fault. It has been stated many times that this library will generally not be changed to work around non-compliant compilers.

I am using a c++11 compiler. ( The one installed by code::blocks v16.01 )

Of course It is your call whether or not to enable your parser to compile out of the box with a widely used compiler. However, I think you should point to a straightforward hack that will enable it to do so, and one that does not involve slashing at the mingw installation. Closing this issue while leaving the situation in such a mess seems rather unfriendly towards a class of potential users, IMHO

You may have a C++11 Compiler, but you may be missing a C++11 standard library (which would provide std::to_string).

It if was a C++11 compliant compiler and library, then it wouldn't require this hacking.

It's up to @nlohmann whether or not any changes are made here, but he's expressed many times that he's not going to hack up the library to support non-conforming toolchains.

One more time: I am not asking that anybody hack the parser. I think you should provide a simple and straightforward and complete hack that users can apply themselves to get things running.

The hack pointed to by the README is scary, the hack you supplied on May 2016 points in a good direction, but is incomplete.

I don't have that compiler, so I can't do that. If someone else that did were to do that and post it here, it would be most helpful.

I don't have that compiler, so I can't do that

the code::blocks installation is freely available from their site http://www.codeblocks.org/downloads

If someone else that did were to do that and post it here, it would be most helpful.

I posted it in my first comment above.

So if you already have it, then what are you looking for?

@JamesBremner Thanks for your fix. As I described before, I shall not add it to the library, because it is only required for non-compliant compilers/standard libraries. As for the README, I am not sure what to write - the links describe how to "fix" the problem; your code shows how to "fix" the library.

I had a look at the website of code::blocks. They say that they support several compilers. Can you try using Clang?

then what are you looking for?

I am looking to be helpful to other people who encounter this problem. If you google it, you will see that these people are quite numerous. I expect that they are many more who simply give up on your parser when they encounter a long list of compiler errors as soon as they try to use it.

Your parser looks to be quite an improvement in other ways to the one I have been using for several years, with much better support. So, if you insist on a selfish reason, then the more people who use this library because it works out of the box, then the better this library will become and I will benefit from any such improvements.

@nlohmann You are welcome.

the README, I am not sure what to write - the links describe how to "fix" the problem;

Not really, they don't. The link to the ancient ( 2012 ) hack to the mingw installation is impossibly scary. Who knows if it still works? The thread on this issue is very long and confusing and the best fix I could find within it, by @gregmarr, is incomplete - it doesn't handle the compiler errors generated by stoi and snprintf.

Can you try using Clang?

Sorry, but no. I have several years of work which all use the code::blocks installation. The build instructions that I have to lead my clients through for all this stuff are tough enough without having to add yet another step to swap out the compiler that comes packaged with codeblocks.

Then again, what about http://stackoverflow.com/questions/12975341/to-string-is-not-a-member-of-std-says-g-mingw/12975602#12975602?

This issue has been fixed in MinGW-w64 distros higher than GCC 4.8.0 provided by the MinGW-w64 project. Despite the name, the project provides toolchains for 32-bit along with 64-bit. The Nuwen MinGW distro also solves this issue.

I have several clients who are accustomed to a long list of build instructions including "Download and install the code:blocks IDE" Although they are unaware of it, this simple step not only gives them the IDE, but also a mingw distro with a g++ compiler. Asking my clients to muck around with integrating different distros with the current codeblocks release, all so that I can use a sexy new json parser in some code that they never look at - well, it just isn't going to sell.

I guess the point is that it is much easier to do a global search and replace, then insert a small chunk of new code into your json.hpp file.

The code::blocks installation works out-of-the-box and everything I do depends on it - so, please, stop suggesting that I hack at it.

I would prefer to point my clients to your website and tell them to download an 'official' version of your code If necessary I can fork your repo, install the fix and point my clients there. I just thought you would welcome the opportunity to gain a new class of users and I could avoid maintaining a copy of your code.

Bad news: the fix does not work in real code.

If more that one file includes json.hpp, then I get multiple definition linker errors.

The problem is that the implementation of the replacement functions cannot be placed in the header, but must be in a single cpp file.

This rather wrecks the beatiful simplicity of integrating your package.

One extreme is to support one specific version of one specific compiler on one specific platform. Another absurd extreme is to support all versions of all compilers out there and all of their warts. Clearly, the line must be drawn somewhere. I think most would agree that "ISO c++11" is a simpler and cleaner differentiation than "ISO c++11 or that one version of code::blocks"

The code::blocks installation works out-of-the-box and everything I do depends on it - so, please, stop suggesting that I hack at it.

I will.

But I also will not add those parts that MinGW failed to implement into my library. As much as it hurts to hear that people may not be able to use the library: please understand that it may not make sense for me to support an objectively broken C++11 system.

Please note:

C:\Program Files (x86)\CodeBlocks16\MinGW\bin>g++ --version
g++ (tdm-1) 4.9.2

The README says

Currently, the following compilers are known to work:

GCC 4.9 - 6.0 (and possibly later)

Yes. And there is the note on the MinGW bug right below.

I think we won't find a solution here:

  • I will not adjust the library to implement the subset of the STL that is missing in MinGW. This just would not make sense.
  • You will not change the compiler or "hack" the shipped STL. I can understand this.

Unless there is another solution, unfortunately this library is not a candidate for a vanilla code:blocks installation.

But the note is not helpful. The fixes mentioned do not work - I have tried them.

Anyway, I am on the point of giving up on this. 5 hours and counting.

There does not seem to be any obvious way to serialize ( convert a json object to a test string )

My old parser was happy with

  json::Object j;
  ...populate...
  string text =  json::Serialize( j );

but this throws an exception

nlohmann::json j
... populate ...
string text = j.get<string>();

Surely a one line to convert a json object into the equivalent human readable form is a basic requirement for a parser? I must be missing something.

It's j.dump();

@gregmarr Thanks! Works perfectly

I must say the prompt support is impressive!

But the note is not helpful. The fixes mentioned do not work - I have tried them.

The comments on StackOverflow sounded promising. I am not aware of a different solution.

@nlohmann I think we won't find a solution here:

OK. The elegance of the parser and the prompt support makes me wish to continue.

I will fork your repo, install the fix ( the one that works! ) and point my clients there.

I am using the library with code::blocks 13.12, which uses the gcc installed in the system. gcc is here
gcc version 4.9.2 (Raspbian 4.9.2-10)
It works out of the box, but you need to enable C++11 in the compiler options.

Just go to Settings->Compiler and tick the option
[ ] Have g++ follow the C++11 ISO C++ language Standard [-std=c++11]

The library will work perfectly then. "out of the box"!

@JamesBremner Can you comment on @tksatware 's observation?

I am using the code::blocks v16.1 with C++11 enabled @tksatware must be doing something more, since he using a much older version of codeblocks

@JamesBremner what does
gcc -v
show?

C:\Program Files (x86)\CodeBlocks16\MinGW\bin>g++ --version
g++ (tdm-1) 4.9.2

gcc version 4.9.2 (Raspbian 4.9.2-10)

This looks very linuxy. I am runninning mingw under windows.

@JamesBremner I will install it Code::Blocks tomorrow under Windows and have a look. On Windows, I am using VS2015 Update 3, which also works fine. The mingw road was always too hacky for me.
But actually, this is gcc 4.9.2 in disguise and should work.

Here is the v2.1.1 release fixed up to compile under windows code::blocks v16.1

https://github.com/JamesBremner/nlohmann-json-parser-for-mingw

Nice work. Please note that the library is called "JSON for Modern C++" and is more than just a parser, so I would suggest you change the README from "This is a copy of the modern C++ JSON parser" to "This is a copy of JSON for Modern C++".

If more that one file includes json.hpp, then I get multiple definition linker errors.
The problem is that the implementation of the replacement functions cannot be placed in the header, but must be in a single cpp file.

Sounds like you were missing an inline.

@gregmarr Good idea. I have re-implemented the missing functions in the header file using inline and so the cpp source file is no longer needed. At the cost of a little bloat, the neat header only design is restored.

I have to note that the inline was also missing form the fix that you posted back in May.

I have replaced my old JSON parser with yours in my first project - a simple open source scheduler. The application source code replacement was very straightforward ( once the compile problems were sorted ).

I do like the automatic handling of json objects versus json arrays. So far, everything is simply just a nlohmann::json

FYI, here is the commit

JamesBremner/schedule@46a5002

@JamesBremner Cool. FYI, I wrote a template function, which is automatically inline.