json11 icon indicating copy to clipboard operation
json11 copied to clipboard

MSVC12 Compatibility

Open PaulFreund opened this issue 10 years ago • 5 comments

I really like the library design and would like to use it cross platform. Unfortunately there are a few roadblocks for using it with MSVC12 (VS2013):

  • In json11.cpp the Statics struct can't be initialized because not every member has an initializer
  • Missing noexcept and snprintf
  • The templates that should define implicit constructors for map and vector like objects seem to fail because std::declval<V>() can not be properly resolved and therefore begin can't be found

The first one can be easily fixed by removing the initializers and adding them to the initializer-list in statics():

struct Statics {
    const std::shared_ptr<JsonValue> null;
    const std::shared_ptr<JsonValue> t;
    const std::shared_ptr<JsonValue> f;
    const string empty_string;
    const vector<Json> empty_vector;
    const map<string, Json> empty_map;
};

const Statics & statics() {
    static const Statics s {
        make_shared<JsonNull>(),
        make_shared<JsonBoolean>(true),
        make_shared<JsonBoolean>(false),
        "",
        vector<Json>(),
        map<string, Json>()
    };
    return s;
}

The missing noexcept and sprintf are a bit harder. MSVC12 does not (yet) include them. It is possible to create a preprocessor define for noexcept after the STL header includes (as an error is thrown when trying to define the missing noexcept myself). snprintf can be replaced by _snprintf but unfortunately behaves a bit different (snprintf truncates and always 0-terminates, _snprintf does not 0-terminate if the buffer is too small, also the return values are different which are not used anyway).

I didn't invest enough much time digging in c++11s templating features to understand the third problem yet. A simple solution is to comment out the two constructors but I am sure there is a better solution.

This is an issue for me and I don't know if you are interested in supporting MSVC12 (don't know if this gets better with the next compiler update).

PS: Having this library header only would be really nice too, but that's secondary for now

PaulFreund avatar Apr 21 '14 18:04 PaulFreund

Hm, apparently VS2013 is supposed to support declval. But, it looks like I forgot to include in json11.hpp. It could be that declval is accidentally available on gcc/clang because of the other includes, but not in MSVC. Does adding that #include fix it?

json11 only uses snprintf to print numbers, so it should be "safe" to replace all instances of snprintf with sprintf... I'd want to triple-check all the buffer sizes, though.

j4cbo avatar Apr 21 '14 19:04 j4cbo

I forgot to mention that I already added <type_traits> to check if this is the issue. Unfortunately not, for reference here is my build output: https://gist.github.com/PaulFreund/11154815

PaulFreund avatar Apr 21 '14 20:04 PaulFreund

Just wanted to tell you that I created a copy for me that is header only and compatible with gcc and msvc12 although I currently excluded the two templates that won't compile with msvc12. It's currently very rough and looks like patchwork but it works for now. Currently I am looking into making the objects mutable so I can spare a few copies.

PaulFreund avatar Apr 25 '14 16:04 PaulFreund

I was able to get it to compile by adding this right above namespace json11

#ifdef _MSC_VER
    #if _MSC_VER <= 1800 // VS 2013
        #define noexcept
        #define snprintf _snprintf_s
    #endif
#endif

_snprintf_s is identical to the Unix snprintf, and since noexcept isn't supported in VS2013, we just erase them.

Intellisense still doesn't like the fail method, but it seems mostly harmless.

malamanteau avatar Feb 03 '15 22:02 malamanteau

@retrop we can mimic noexcept with throw() and I don't think snprintf is equal to _snprintf_s

see:

  • http://stackoverflow.com/questions/12833241/difference-between-c03-throw-specifier-c11-noexcept
  • https://github.com/llvm-mirror/libcxx/blob/master/include/support/win32/support.h

note: I know that on paper noexcept != throw() but the way it is used in json11 they are more or less equal.

#ifdef _MSC_VER
    #if _MSC_VER <= 1800 // VS 2013
        #define noexcept throw()
        #define snprintf _snprintf
    #endif
#endif

stevenhoving avatar Jun 11 '15 10:06 stevenhoving