Repository navigation
json::value_t can't be a map's key type in VC++ 2015 #486
Description
Activity
Can you please provide the error messages from MSVC?
No problem. Here:
Z:\>cl /EHsc test3.cpp test3.cpp C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xstddef(239): error C2593: 'operator <' is ambiguous C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(436): note: could be 'bool std::operator <(const std::error_condition &,const std::error_condition &) noexcept' C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(427): note: or 'bool std::operator <(const std::error_code &,const std::error_code &) noexcept' z:\json.hpp(171): note: or 'bool nlohmann::detail::operator <(const nlohmann::detail::value_t,const nlohmann::detail::value_t) noexcept' [found using argument-dependent lookup] C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xstddef(239): note: while trying to match the argument list '(const nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t, const nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t)' C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xstddef(238): note: while compiling class template member function 'bool std::less<_Kty>::operator ()(const _Ty &,const _Ty &) const' with [ _Kty=nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t, _Ty=nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t ] C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\map(210): note: see reference to function template instantiation 'bool std::less<_Kty>::operator ()(const _Ty &,const _Ty &) const' being compiled with [ _Kty=nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t, _Ty=nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t ] C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\type_traits(421): note: see reference to class template instantiation 'std::less<_Kty>' being compiled with [ _Kty=nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t ] C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xutility(265): note: see reference to class template instantiation 'std::is_empty<_Ty1>' being compiled with [ _Ty1=std::less<nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t> ] C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xtree(957): note: see reference to class template instantiation 'std::_Tree_comp_alloc<_Traits>' being compiled with [ _Traits=std::_Tmap_traits<nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t,std::string,std::less<nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t>,std::allocator<std::pair<const nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t,std::string>>,false> ] C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\map(73): note: see reference to class template instantiation 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>' being compiled with [ _Kty=nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t, _Ty=std::string, _Pr=std::less<nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t>, _Alloc=std::allocator<std::pair<const nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t,std::string>> ] test3.cpp(11): note: see reference to class template instantiation 'std::map<nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t,std::string,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' being compiled with [ _Kty=nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t, _Ty=std::string ]Could you try explicitly to pass
nlohmann::detail::operator<asComparetemplate argument to themap?I don't know how to pass the operator itself, but I tried passing a functor, like this:
#include <string> #include <map> #include <iostream> #include "json.hpp" using JSON = nlohmann::json ; int main (){ using namespace std ; struct value_tCompare { bool operator()(const JSON::value_t& a, const JSON::value_t& b) const{ return a < b ; } } ; map<JSON::value_t, string, value_tCompare > jsonTypes ; jsonTypes[JSON::value_t::array] = "array" ; cout << jsonTypes[ JSON({"val1", 123, false}) ] << endl ; }And the result was this:
Z:\>cl /EHsc test3.cpp test3.cpp test3.cpp(13): error C2593: 'operator <' is ambiguous C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(436): note: could be 'bool std::operator <(const std::error_condition &,const std::error_condition &) noexcept' C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(427): note: or 'bool std::operator <(const std::error_code &,const std::error_code &) noexcept' z:\json.hpp(171): note: or 'bool nlohmann::detail::operator <(const nlohmann::detail::value_t,const nlohmann::detail::value_t) noexcept' [found using argument-dependent lookup] test3.cpp(13): note: while trying to match the argument list '(const nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t, const nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::value_t)'Then I tried using
nlohmann::detail::operator<explicitly inside the functor, and it compiled successfully.#include <string> #include <map> #include <iostream> #include "json.hpp" using JSON = nlohmann::json ; int main (){ using namespace std ; struct value_tCompare { bool operator()(const JSON::value_t& a, const JSON::value_t& b) const{ return nlohmann::detail::operator<(a,b) ; } } ; map<JSON::value_t, string, value_tCompare > jsonTypes ; jsonTypes[JSON::value_t::array] = "array" ; cout << jsonTypes[ JSON({"val1", 123, false}) ] << endl ; }This seems to be an argument-dependent lookup issue. For some reason the compiler is not prioritizing
nlohmann::detail::operator<over the others.Hopefully there is a way to solve it, so we don't need this workaround.
This seems to be an issue where @theodelrieu may know more.
I will take a look tomorrow, this looks like a MSVC-specific weirdness at first sight
Reacted by Niels LohmannThere is a workaround mentioned in this StackOverflow thread
Should we add this to the library?namespace std { template <> struct less<::nlohmann::detail::value_t> { bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept { return ::nlohmann::detail::operator<(lhs, rhs); } }; }
Reacted by Niels LohmannIs it safe to add this to the
stdnamespace? @gregmarr ?That's a template specialization, it's allowed and safe.
Plus, this is what the default
std::less<nlohmann::detail::value_t>looks like on the other platforms.- added a commit that references this issue
on Mar 11, 2017 The following code now compiles with MSVC 2015 (see https://ci.appveyor.com/project/nlohmann/json/build/1765):
std::map<json::value_t, std::string> jsonTypes ; jsonTypes[json::value_t::array] = "array";
@Getfree Can you try this version of the code please: f4126e4
- addedsolution: proposed fixa fix for the issue has been proposed and waits for confirmationa fix for the issue has been proposed and waits for confirmation
on Mar 11, 2017 I added the fixed version to my project and it compiled successfully.
Many thanks.
- removedsolution: proposed fixa fix for the issue has been proposed and waits for confirmationa fix for the issue has been proposed and waits for confirmation
on Mar 12, 2017
The following code does not compile in Visual Studio 2015, but compiles fine in GCC.
Wandbox: http://melpon.org/wandbox/permlink/Izdt8DW4UGpVQdUd