Json: Using tsl::ordered_map

Created on 4 Apr 2017  路  6Comments  路  Source: nlohmann/json

Hi!

I'm using Visual Studio C++ 2017 and I get the following error when I try to use tsl::ordered_map with basic_json:

'std::pair::second' uses undefined class 'nlohmann::basic_json'

confirmed bug stale

Most helpful comment

It seems ObjectType can only be a class which takes std::less<StringType> as third class template parameter and an allocator as fourth. See this using object_t line.

Also tsl::ordered_map needs an allocator with std::pair<Key, T> as value_type and not std::pair<const Key, T>.

One way to overcome these issues could be to use something like:

template<class Key, class T, class Ignore, class Allocator,
         class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>,
         class AllocatorPair = typename std::allocator_traits<Allocator>::template rebind_alloc<std::pair<Key, T>>,
         class ValueTypeContainer = std::vector<std::pair<Key, T>, AllocatorPair>>
using ordered_map = tsl::ordered_map<Key, T, Hash, KeyEqual, AllocatorPair, ValueTypeContainer>;

using json = nlohmann::basic_json<ordered_map>;

But it's probably not the best solution.

The best solution would be to be able to use any associative container no matter where the position of the Allocator class parameter is, but I don't know how we could do that properly.

All 6 comments

Related to #485.

I failed to compile an example myself, but did not find the time to dig into it.

It seems ObjectType can only be a class which takes std::less<StringType> as third class template parameter and an allocator as fourth. See this using object_t line.

Also tsl::ordered_map needs an allocator with std::pair<Key, T> as value_type and not std::pair<const Key, T>.

One way to overcome these issues could be to use something like:

template<class Key, class T, class Ignore, class Allocator,
         class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>,
         class AllocatorPair = typename std::allocator_traits<Allocator>::template rebind_alloc<std::pair<Key, T>>,
         class ValueTypeContainer = std::vector<std::pair<Key, T>, AllocatorPair>>
using ordered_map = tsl::ordered_map<Key, T, Hash, KeyEqual, AllocatorPair, ValueTypeContainer>;

using json = nlohmann::basic_json<ordered_map>;

But it's probably not the best solution.

The best solution would be to be able to use any associative container no matter where the position of the Allocator class parameter is, but I don't know how we could do that properly.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

While trying to get ordered json working (and got stuck on fifo_map) I tried the other recommended implementation in tsl::ordered_map, using this code:

#include <nlohmann/json.hpp>
#include <tsl/ordered_map.h>
// for convenience
using json = nlohmann::basic_json<tsl::ordered_map>;

but I am getting the same error as the OP (@arvidsson).

C:\PROGRA~2\MICROS~2\2017\COMMUN~1\VC\Tools\MSVC\1416~1.270\bin\HostX64\x64\cl.exe  /nologo /TP  -ID:\Dev\include\xtensor -ID:\Dev\include\nlohmann -ID:\Dev\include /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1   -std:c++17 /showIncludes /Fohmdq\CMakeFiles\hmdq.dir\hmdq.cpp.obj /Fdhmdq\CMakeFiles\hmdq.dir\ /FS -c ..\..\hmdq\hmdq.cpp
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\utility(320): error C2079: 'std::pair<Key,T>::second' uses undefined class 'nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>'
          with
          [
              Key=std::string,
              T=nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>
          ]
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\deque(926): note: see reference to class template instantiation 'std::pair<Key,T>' being compiled
          with
          [
              Key=std::string,
              T=nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>
          ]
  d:\dev\include\tsl\ordered_hash.h(228): note: see reference to class template instantiation 'std::deque<std::pair<Key,T>,Allocator>' being compiled
          with
          [
              Key=std::string,
              T=nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>,
              Allocator=std::allocator<std::pair<std::string,nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>
          ]
  D:\Dev\include\tsl/ordered_map.h(112): note: see reference to class template instantiation 'tsl::detail_ordered_hash::ordered_hash<std::pair<Key,T>,tsl::ordered_map<Key,T,nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::object_comparator_t,std::allocator<std::pair<const StringType,nlohmann::basic_json<tsl::ordered_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>,std::allocator<std::pair<Key,T>>,std::deque<std::pair<Key,T>,Allocator>,uint_least32_t>::KeySelect,tsl::ordered_map<Key,T,nlohmann::basic_json<tsl::ordered_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::object_comparator_t,std::allocator<std::pair<const StringType,nlohmann::basic_json<tsl::ordered_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>,Allocator,std::deque<std::pair<Key,T>,Allocator>,uint_least32_t>::ValueSelect,Hash,KeyEqual,Allocator,ValueTypeContainer,IndexType>' being compiled
          with
          [
              Key=std::string,
              T=nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>,
              StringType=std::string,
              Allocator=std::allocator<std::pair<std::string,nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>,
              Hash=nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::object_comparator_t,
              KeyEqual=std::allocator<std::pair<const std::string,nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>,
              ValueTypeContainer=std::deque<std::pair<std::string,nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>,std::allocator<std::pair<std::string,nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>>,
              IndexType=uint_least32_t
          ]
  D:\Dev\include\nlohmann/json.hpp(15909): note: see reference to class template instantiation 'tsl::ordered_map<StringType,nlohmann::basic_json<tsl::ordered_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>,nlohmann::basic_json<tsl::ordered_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::object_comparator_t,std::allocator<std::pair<const StringType,nlohmann::basic_json<tsl::ordered_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>,std::allocator<std::pair<Key,T>>,std::deque<std::pair<Key,T>,Allocator>,uint_least32_t>' being compiled
          with
          [
              StringType=std::string,
              Key=std::string,
              T=nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>,
              Allocator=std::allocator<std::pair<std::string,nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>
          ]
  ..\..\hmdq\hmdq.cpp(51): note: see reference to class template instantiation 'nlohmann::basic_json<tsl::ordered_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>' being compiled
  ninja: build stopped: subcommand failed.

It seems that neither fifo_map nor tsl::ordered_map works with json and MSVC compiler. Does anyone knows any other solution which could work?

Or which compiler supports them as I assume some must as the README recommends both?

To be able to use basic_json with tsl::ordered_map, I wrote this patch https://github.com/ilelann/json/commit/f106d6ba3abcee65765dcd5734fb670d539920d6
As you can see, I "solved" the point raised here https://github.com/nlohmann/json/issues/546#issuecomment-304447518 about the position of Allocator template argument by introducing a small traits class.
Ultimately, I did not create a pull request for this because I was happy with fifo_map.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

afowles picture afowles  路  3Comments

SimplyLiz picture SimplyLiz  路  3Comments

alienzj picture alienzj  路  4Comments

Prati369 picture Prati369  路  4Comments

zkelo picture zkelo  路  3Comments