Skip to content
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

::get<int>() fails in new(er) release [MSVC] #780

Closed
sfinktah opened this issue Oct 13, 2017 · 21 comments
Closed

::get<int>() fails in new(er) release [MSVC] #780

sfinktah opened this issue Oct 13, 2017 · 21 comments
Labels

Comments

@sfinktah
Copy link

sfinktah commented Oct 13, 2017

Compiler: MSVC 15.1 (2017) with VS2015 libraries etc.

Was working with: c42273d (2.1.1)

    hsv_t(const json &values)
        : hsv_t( 
            wrap360( values[0].get<int>()),
            clamp100(values[1].get<int>()),
            clamp100(values[2].get<int>()),
            clamp100(values[3].get<int>())){}

Fails with: d300a8e (2.1.1) latest dev

Replaced with:
    hsv_t(const json &values)
        : hsv_t( 
            wrap360( static_cast<int>(values[0])),
            clamp100(static_cast<int>(values[1])),
            clamp100(static_cast<int>(values[2])),
            clamp100(static_cast<int>(values[3]))){}

But error just moved to json.hpp +9836

    template < typename ValueType, typename std::enable_if <
                   not std::is_pointer<ValueType>::value and
                   not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
                   not std::is_same<ValueType, typename string_t::value_type>::value
#ifndef _MSC_VER  // fix for issue #167 operator<< ambiguity under VS2015
                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#endif
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSC_VER) && _MSC_VER >1900 && defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
                   and not std::is_same<ValueType, typename std::string_view>::value
#endif
                   , int >::type = 0 >
    operator ValueType() const
    {
        // delegate the call to get<>() const
        return get<ValueType>();
    }
1>E:\git\infamous-dll\src\vendor\sfinktah\include\json.hpp(9836): error C2672: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get': no matching overloaded function found
1>e:\git\infamous-dll\src\Update/Types.h(333): note: see reference to function template instantiation 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::operator ValueType(void) const<float,0>' being compiled
1>        with
1>        [
1>            ValueType=float
1>        ]
1>e:\git\infamous-dll\src\Update/Types.h(333): note: see reference to function template instantiation 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::operator ValueType(void) const<float,0>' being compiled
1>        with
1>        [
1>            ValueType=float
1>        ]
1>E:\git\infamous-dll\src\vendor\sfinktah\include\json.hpp(9836): error C2783: 'const PointerType nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get(void) noexcept const': could not deduce template argument for '__formal'
1>E:\git\infamous-dll\src\vendor\sfinktah\include\json.hpp(9663): note: see declaration of 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get'
1>E:\git\infamous-dll\src\vendor\sfinktah\include\json.hpp(9836): error C2783: 'PointerType nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get(void) noexcept': could not deduce template argument for '__formal'
1>E:\git\infamous-dll\src\vendor\sfinktah\include\json.hpp(9651): note: see declaration of 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get'
1>E:\git\infamous-dll\src\vendor\sfinktah\include\json.hpp(9836): error C2783: 'ValueType nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get(void) noexcept(<expr>) const': could not deduce template argument for '__formal'
1>E:\git\infamous-dll\src\vendor\sfinktah\include\json.hpp(9614): note: see declaration of 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get'
1>E:\git\infamous-dll\src\vendor\sfinktah\include\json.hpp(9836): error C2783: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer> nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get(void) const': could not deduce template argument for '__formal'
1>E:\git\infamous-dll\src\vendor\sfinktah\include\json.hpp(9509): note: see declaration of 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get'
@sfinktah sfinktah changed the title ::get<int>() fails in new(er) release ::get<int>() fails in new(er) release [MSVC] Oct 13, 2017
@nlohmann
Copy link
Owner

How does values look like? Does the error still occur with the latest develop version?

@nlohmann nlohmann added the platform: visual studio related to MSVC label Oct 14, 2017
@sfinktah
Copy link
Author

that is the latest develop version.

* develop d300a8e :rotating_light: fixed warnings #776

values is just an array of 4 numbers, nothing special. but this is all compile time, so the actual contents of values is only hypothetical.

sorry, forgot to add that the function is a class constructor.

the main reason I updated from the previous release I was running, is that I couldn't serialize BYTE (__uint8) or obvious char/__int8 values. But I thought it best to see if that had been addresses in a more recent commit before searching issues.

@sfinktah
Copy link
Author

Here's a complete-ish copy of the class header:

struct hsv_t {
    int h;
    int s;
    int v;
    int a;

    constexpr hsv_t() : h(0), s(0), v(0), a(0) {}
    constexpr hsv_t(int h, int s, int v, int a) : h(wrap360(h)), s(clamp100(s)), v(clamp100(v)), a(clamp255(a)){}
    constexpr hsv_t(int h, int s, int v) : hsv_t(h, s, v, 255) {}
    constexpr hsv_t(float h, float s, float v) : hsv_t(h * 360, s * 100, v * 100, 255) {}

    template<typename T>
    constexpr hsv_t(T (&values)[3])
        : hsv_t( 
            static_cast<int>(values[0]), 
            static_cast<int>(values[1]), 
            static_cast<int>(values[2])){}

    template<typename T>
    constexpr hsv_t(T (&values)[4])
        : hsv_t( 
            static_cast<int>(values[0]), 
            static_cast<int>(values[1]), 
            static_cast<int>(values[2]), 
            static_cast<int>(values[3])){}

    template<typename T>
    constexpr hsv_t(std::array<T, 4> values)
        : hsv_t( 
            static_cast<int>(values[0]), 
            static_cast<int>(values[1]), 
            static_cast<int>(values[2]), 
            static_cast<int>(values[3])){}

    hsv_t(const json &values)
        : hsv_t( 
            wrap360( values[0].get<int>()),
            clamp100(values[1].get<int>()),
            clamp100(values[2].get<int>()),
            clamp100(values[3].get<int>())){}

There's probably a fancy way to cast the json array as a std::container, but it eludes me.

I should add, that this isn't the only place the error occurred, simply the first place. I can make you a test project for MSVC if you like.

@nlohmann
Copy link
Owner

What is clamp100 and wrap360?

@sfinktah
Copy link
Author

sfinktah commented Oct 17, 2017

LOL, I really should have looked for a simpler instance, in-fact, I will do exactly that. It's dealing with the HSV color palette, so wrap360 wraps around 360°, and clamp is ... a clamp.

template <typename T>
constexpr uint8_t clamp100(T val) {
    #define MIN 0
    #define MAX 100
    return (
        val > MAX ? MAX :
        val < MIN ? MIN :
        val
    );
    #undef MIN
    #undef MAX
}

template <typename T>
constexpr uint16_t wrap360(T val) {
    #define MIN 0
    #define MAX 360
    return (
        (val + MAX) % MAX
    );
    #undef MIN
    #undef MAX
}

I did find out something new though -- because the constructor taking json arguments isn't marked explicit, there was an edge case where

    std::vector<int> v{1, 2, 3};
    rgb_t color = rgb_t(v);

was passed through the json constructor.

The constructor is marked explicit now.

@sfinktah
Copy link
Author

sfinktah commented Oct 17, 2017

Hmmm.... turns out, there is no simpler instance of it failing. Just the hsv_t and a similar rgb_t struct.

I did remove the misc. clamps, and such, and used the original json::get<int> syntax. The errors may be different, and plausibly enlightening. (Though not for me, I'm afraid).

    explicit hsv_t(const json &values)
        : hsv_t( 
            values[0].get<int>(),
            values[1].get<int>(),
            values[2].get<int>(),
            values[3].get<int>()
		){}

The errors are repeated for each of the 4 lines of the constructor.

1>Types.h(1141):  error C2672: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get': no matching overloaded function found
1>Types.h(1141):  error C2783: 'const PointerType nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get(void) noexcept const': could not deduce template argument for '__formal'
1>json.hpp(9663): note: see declaration of 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get'
1>Types.h(1141):  error C2783: 'PointerType nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get(void) noexcept': could not deduce template argument for '__formal'
1>json.hpp(9651): note: see declaration of 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get'
1>Types.h(1141):  error C2783: 'ValueType nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get(void) noexcept(<expr>) const': could not deduce template argument for '__formal'
1>json.hpp(9614): note: see declaration of 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get'
1>Types.h(1141):  error C2783: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer> nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get(void) const': could not deduce template argument for '__formal'
1>json.hpp(9509): note: see declaration of 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get'

I was especially thrown by could not deduce template argument for '__formal' ...

@sfinktah
Copy link
Author

Okay, I went hunting for other occurrences of .get<> and checked for Intellisense (shudder) errors.

These weren't immediately apparent, because the compiler halts after the errors above.

"No instance of overloaded function basic_json... matches the argument list. Object type is: json"

        if (j.is_string()) {
            result = getTextFromLabel(ptr, j.get<std::string>().c_str());

"No instance of overloaded function basic_json... matches the argument list. Object type is: basic_json<std::map ... adl_serializer>"

for (int ii = 0; ii < a.size(); ii++) {
	// Let keep it simple for demonstration purposes:
	printf("%i", a[ii].get<int>());
}

@theodelrieu
Copy link
Contributor

This is very strange, I've seen some projects like sqlpp11 that were broken by the latest MSVC 2017 release...

Might it be the case here?

@sfinktah
Copy link
Author

Just tested a compile using the 2015 command line tools, same result.

Interestingly, a quick test program which should have caused the same error, compiled without issue.

confused

#include "json.hpp"
using json = nlohmann::json;

int main(int argc, char **argv) {
    json j = { {"list", {1, 0, 2} } };

    json j2 = j["list"];
    auto item = j2[1].get<int>();
}

A quick google search on the error message produced (apart from this issue) an article about constexpr causing issues.

https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/9c04ff5b-b542-4b84-80d3-6d65159becbc/type-deduction-failure-when-using-a-constexpr-function?forum=vclanguage

@nlohmann
Copy link
Owner

This really sounds like a bug. Did you try (just to make sure) to remove the constexpr from your code and see if it compiles then?

@theodelrieu
Copy link
Contributor

From your snippet, it seems like there's a bug in your macro.

Did you forget the double quotes?

j["#X"]

@gregmarr
Copy link
Contributor

No, #X makes X into a quoted string.

@nlohmann
Copy link
Owner

I am not sure whether I can help with #780 (comment), especially without knowing how SavedVehicleModDBRow looks like.

@gregmarr
Copy link
Contributor

There are no json library functions referenced in that error message. Are you using the library to serialize something that owns a std::vector<SavedVehicleModDBRow>?

@nlohmann nlohmann added the state: needs more info the author of the issue needs to provide more details label Oct 31, 2017
@sfinktah
Copy link
Author

sfinktah commented Nov 4, 2017

@gregmarr yes, that's was implied by my statement "one of the structs for which I have a to_json helper defined"

@nlohmann I wouldn't expect you to. And, it's another issue anyway.

I think I should just delete that last comment regarding the error, and worktree an older commit of the project to determine if the "::get() fails in new(er) release [MSVC]" issue vanished due to changes made to json, or due to the upgrade to MSVC141.

@sfinktah
Copy link
Author

sfinktah commented Nov 4, 2017

Just tested the same commit that had the failing "get()" code in it, with the same compiler and platform toolset, (MSVC140) but with the latest json.hpp, and it compiled without issue.

So I then checked out the latest version of our project, copied the latest json.hpp in, and compiled it with the newest MSVC141/C++17 and it also compiled without issue.

So, I think we can call that resolved.

@sfinktah sfinktah closed this as completed Nov 4, 2017
@nlohmann nlohmann removed the state: needs more info the author of the issue needs to provide more details label Nov 26, 2017
@jmorei
Copy link

jmorei commented Mar 26, 2018

Is anybody else still having a problem with this? In Visual Studio 15.6.4, I'm unable to compile the following example:

#include "json.hpp"

namespace quicktype {
    using nlohmann::json;

    struct TestSchema {
        double test_val;
    };
    
    inline json get_untyped(const json &j, const char *property) {
        if (j.find(property) != j.end()) {
            return j.at(property).get<json>();
        }
        return json();
    }
}

namespace nlohmann {
    inline void from_json(const json& _j, struct quicktype::TestSchema& _x) {
        _x.test_val = _j.at("test_val").get<double>();
    }

    inline void to_json(json& _j, const struct quicktype::TestSchema& _x) {
        _j = json::object();
        _j["test_val"] = _x.test_val;
    }
}

The error messages are:

<redacted>\test_schema.cpp(31): error C2672: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get': no matching overloaded function found
<redacted>\test_schema.cpp(31): error C2783: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer> nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get(void) const': could not deduce template argument for '__formal'
<redacted>\include\nlohmann\json.hpp(12096): note: see declaration of 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::get'
<redacted>\test_schema.cpp(36): error C2679: binary '=': no operator found which takes a right-hand operand of type 'const double' (or there is no acceptable conversion)
<redacted>\include\nlohmann\json.hpp(11471): note: could be 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer> &nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::operator =(nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>) noexcept' (compiling source file test_schema.cpp)
<redacted>\test_schema.cpp(36): note: while trying to match the argument list '(nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>, const double)'

It seems pretty clearly to be a failure on Visual Studio's C++11 support, but I'm curious if there's any known workaround, since people further up in the thread seemed to have found success.

@theodelrieu
Copy link
Contributor

I don't know if that will help, but you really should not add free functions in the nlohmann namespace.

Could you put the from/to_json in the quicktype namespace, just above TestSchema's definition?

@jmorei
Copy link

jmorei commented Mar 27, 2018

Thanks, @theodelrieu -- that did indeed solve my problem. I misunderstood the docs about where the to_json / from_json functions should live, and it looks like the code generation tool I was using made the same error.

@theodelrieu
Copy link
Contributor

Glad to hear :)

@Exophobias
Copy link

Hello sfinktah!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants