Skip to content

Using fifo_map #485

Closed
Closed

Description

@adah1972

The document says "you can specialize the object type with containers like tsl::ordered_map or nlohmann::fifo_map". I had a try with simple code like:

#include "fifo_map.hpp"
#include "json.hpp"

using json = nlohmann::basic_json<nlohmann::fifo_map>;

int main()
{
    json j;
}

It fails the compilation noisily. Would you please fix the issue, and/or clarify in the document how this should be done?

Activity

  1. nlohmann commented on Mar 7, 2017

    @nlohmann
    Owner

    Can you please provide the compiler error messages?

  2. adah1972 commented on Mar 7, 2017

    @adah1972
    Author

    From GCC:

    In file included from test.cpp:1:0:
    fifo_map.hpp: In instantiation of 'nlohmann::fifo_map<Key, T, Compare, Allocator>::fifo_map() [with Key = std::__cxx11::basic_string<char>; T = nlohmann::basic_json<nlohmann::fifo_map>; Compare = std::less<std::__cxx11::basic_string<char> >; Allocator = std::allocator<std::pair<const std::__cxx11::basic_string<char>, nlohmann::basic_json<nlohmann::fifo_map> > >]':
    /usr/local/Cellar/gcc/6.3.0_1/include/c++/6.3.0/ext/new_allocator.h:120:4:   required from 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = nlohmann::fifo_map<std::__cxx11::basic_string<char>, nlohmann::basic_json<nlohmann::fifo_map>, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, nlohmann::basic_json<nlohmann::fifo_map> > > >; _Args = {}; _Tp = nlohmann::fifo_map<std::__cxx11::basic_string<char>, nlohmann::basic_json<nlohmann::fifo_map>, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, nlohmann::basic_json<nlohmann::fifo_map> > > >]'
    json.hpp:1634:9:   required from 'static T* nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::create(Args&& ...) [with T = nlohmann::fifo_map<std::__cxx11::basic_string<char>, nlohmann::basic_json<nlohmann::fifo_map>, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, nlohmann::basic_json<nlohmann::fifo_map> > > >; Args = {}; ObjectType = nlohmann::fifo_map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer'
    json.hpp:1701:46:   required from 'nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::json_value::json_value(nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::value_t) [with ObjectType = nlohmann::fifo_map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::value_t = nlohmann::detail::value_t]'
    json.hpp:1917:49:   required from 'nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::basic_json(nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::value_t) [with ObjectType = nlohmann::fifo_map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::value_t = nlohmann::detail::value_t]'
    json.hpp:1941:35:   required from 'nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::basic_json(std::nullptr_t) [with ObjectType = nlohmann::fifo_map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; std::nullptr_t = std::nullptr_t]'
    test.cpp:8:10:   required from here
    fifo_map.hpp:126:63: error: no matching function for call to 'std::less<std::__cxx11::basic_string<char> >::less(std::unordered_map<std::__cxx11::basic_string<char>, long unsigned int, std::hash<std::__cxx11::basic_string<char> >, std::equal_to<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, long unsigned int> > >*)'
         fifo_map() : m_keys(), m_compare(&m_keys), m_map(m_compare) {}
                                                                   ^
    

    From Clang:

    ./fifo_map.hpp:126:28: fatal error: no matching constructor for initialization
          of 'std::__1::less<std::__1::basic_string<char> >'
        fifo_map() : m_keys(), m_compare(&m_keys), m_map(m_compare) {}
                               ^         ~~~~~~~
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1740:31: note: 
          in instantiation of member function
          'nlohmann::fifo_map<std::__1::basic_string<char>,
          nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer>,
          std::__1::less<std::__1::basic_string<char> >,
          std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>,
          nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer> > > >::fifo_map' requested here
                ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
                                  ^
    ./json.hpp:1634:15: note: in instantiation of function template specialization
          'std::__1::allocator<nlohmann::fifo_map<std::__1::basic_string<char>,
          nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer>,
          std::__1::less<std::__1::basic_string<char> >,
          std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>,
          nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer> > > >
          >::construct<nlohmann::fifo_map<std::__1::basic_string<char>,
          nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer>,
          std::__1::less<std::__1::basic_string<char> >,
          std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>,
          nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer> > > >>' requested here
            alloc.construct(object.get(), std::forward<Args>(args)...);
                  ^
    ./json.hpp:1701:30: note: in instantiation of function template specialization
          'nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator,
          adl_serializer>::create<nlohmann::fifo_map<std::__1::basic_string<char>,
          nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer>,
          std::__1::less<std::__1::basic_string<char> >,
          std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>,
          nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer> > > >>' requested here
                        object = create<object_t>();
                                 ^
    ./json.hpp:1917:31: note: in instantiation of member function
          'nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer>::json_value::json_value' requested here
            : m_type(value_type), m_value(value_type)
                                  ^
    ./json.hpp:1941:11: note: in instantiation of member function
          'nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer>::basic_json' requested here
            : basic_json(value_t::null)
              ^
    test.cpp:8:10: note: in instantiation of member function
          'nlohmann::basic_json<nlohmann::fifo_map, std::vector,
          std::__1::basic_string<char>, bool, long long, unsigned long long, double,
          std::allocator, adl_serializer>::basic_json' requested here
        json j;
             ^
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base:59:30: note: 
          candidate constructor (the implicit copy constructor) not viable: no known
          conversion from 'std::unordered_map<basic_string<char>, std::size_t> *'
          (aka 'unordered_map<std::__1::basic_string<char>, unsigned long> *') to
          'const std::__1::less<std::__1::basic_string<char> >' for 1st argument
    struct _LIBCPP_TYPE_VIS_ONLY less : binary_function<_Tp, _Tp, bool>
                                 ^
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base:59:30: note: 
          candidate constructor (the implicit move constructor) not viable: no known
          conversion from 'std::unordered_map<basic_string<char>, std::size_t> *'
          (aka 'unordered_map<std::__1::basic_string<char>, unsigned long> *') to
          'std::__1::less<std::__1::basic_string<char> >' for 1st argument
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_base:59:30: note: 
          candidate constructor (the implicit default constructor) not viable:
          requires 0 arguments, but 1 was provided
    1 error generated.
    
  3. nlohmann commented on Mar 7, 2017

    @nlohmann
    Owner

    Thanks, I shall have a look.

  4. nlohmann commented on Mar 7, 2017

    @nlohmann
    Owner

    I can confirm the error, but I have no idea how to fix it. I haven't tried fifo_map for this issue in a long time - I only mentioned it in the REAMDE, because I read somewhere that it was used successfully with this library. There may be issues, because fifo_map uses std::unordered_map internally, which is problematic (#164).

  5. arvidsson commented on Apr 4, 2017

    @arvidsson

    Using Visual Studio C++ 2017, I get the following error:
    'add_key': is not a member of 'std::less'

  6. Daniel599 commented on Apr 10, 2017

    @Daniel599
    Contributor

    Hi, I think I found out the problem, I think it's because when you are declaring object_t,
    you use std::less, but not all map-like use std::less, i'm guessing it's because you wanted to set the allocator.
    I can offer a patch:
    Patch (might break people who set the map manually)
    If you still want to keep you inner type allocator aware

    template<class K, class V, class A>
    using default_object_t = std::map<K, V, std::less< K >, A>; // A wrapper class for the new usage

    template <
    template<typename U, typename V, typename... Args> class ObjectType = default_object_t,
    ...
    >
    class basic_json
    {
    using object_t = ObjectType<StringType,
    basic_json,
    AllocatorType<std::pair<const StringType,
    basic_json>>>; // Note I removed std::less
    }

    now if you want to use fifo_map you can by using the follow:

    template<class K, class V, class A>
    using my_obj = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare< K >, A>;

    template<class K, class V, class A>
    using my_obj2 = std::unordered_map<K, V, std::hash< K >, std::equal_to< K >, A>; // Can support also unordered_map

    using my_json = nlohmann::basic_json<my_obj>;

    please note that I haven't fully tested it, just basic example, not sure if it's the right way to do it, just an idea.

    Also I can offer a workaround without changing the json library itself but it's a bit more ugly and will break if you will fix it using the patch above.

    Let me know if you want this patch a pull request.

  7. donho commented on Sep 10, 2017

    @donho

    Using Visual Studio C++ 2017, I get the following error:
    'add_key': is not a member of 'std::less'

    Same error under VS2015.
    I think I will use nlohmann::json without fifo_map :(

  8. nlohmann commented on Sep 10, 2017

    @nlohmann
    Owner

    Related to #660 (comment):

    I really need to remove the hint to fifo_map from the documentation... :-(

  9. tomtachi commented on Sep 10, 2017

    @tomtachi
  10. tomtachi commented on Sep 10, 2017

    @tomtachi
  11. SiebelsTim commented on Oct 2, 2017

    @SiebelsTim

    The fifo_map library uses an uncommon comparator type, which needs to hold a key storage. std::map for example uses std::less by default, which is a simple functor without state.
    The json library follows the pattern of std::map which directly passes std::less<StringType> to the object type. And of course, there is no constructor for std::less<std::string>(std::unordered_map<Key, std::size_t>*). That's the problem.

    It is not possible to solve this without breaking compatibility with one of the libraries.

  12. Daniel599 commented on Oct 2, 2017

    @Daniel599
    Contributor

    As I said before in my previous comment, there is a way to do it without a change in the libraries, it's a workaround which I don't like that much since it will break if the API will change.
    anyway here it's: (be warn - this workaround will break if the template parameters will change)

    #include "json.hpp"
    #include "fifo_map.hpp"
    #include <iostream>
    
    using namespace nlohmann;
    
    // A workaround to give to use fifo_map as map, we are just ignoring the 'less' compare
    template<class K, class V, class dummy_compare, class A>
    using my_workaround_fifo_map = fifo_map<K, V, fifo_map_compare<K>, A>;
    using my_json = basic_json<my_workaround_fifo_map>;
    
    int main()
    {
    	my_json j;
    	j["f"] = 5;
    	j["a"] = 2;
    	my_json j2 = {
    	  {"pi", 3.141},
    	  {"happy", true},
    	  {"name", "Niels"},
    	  {"nothing", nullptr},
    	  {"answer", {
    	    {"everything", 42}
    	  }},
    	  {"list", {1, 0, 2}},
    	  {"object", {
    	    {"currency", "USD"},
    	    {"value", 42.99}
    	  }}
    	};
    
    	std::cout << j << std::endl;
    	std::cout << j2 << std::endl;
    
    	return 0;
    }

    output:

    {"f":5,"a":2}
    {"pi":3.141,"happy":true,"name":"Niels","nothing":null,"answer":{"everything":42},"list":[1,0,2],"object":{"currency":"U
    SD","value":42.99}}
    

    I don't like this workaround very much since it isn't clean and really patchy, but maybe this will give others a better idea about what to do.

  13. 20 remaining items

  14. Daniel599 commented on Oct 26, 2018

    @Daniel599
    Contributor

    it doesn't compile because they are different types.
    if you want same function for both of them, you need to convert processJson into a template function:

    template<class JSONType>
    void processJson(JSONType &j)
    {
    }
    json j1;
    my_json j2;
    
    processJson(j1);
    processJson(j2);
  15. risa2000 commented on Jul 10, 2019

    @risa2000
    Contributor

    I am sorry if this has been already solved, but I am trying to build specialized json with fifo_map, using following code:

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

    and I am hit by the error already reported by @arvidsson above:

    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
    D:\Dev\include\nlohmann\fifo_map.hpp(188): error C2039: 'add_key': is not a member of 'std::less<void>'
      C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\xstddef(278): note: see declaration of 'std::less<void>'
      D:\Dev\include\nlohmann/fifo_map.hpp(187): note: while compiling class template member function 'T &nlohmann::fifo_map<StringType,T,nlohmann::basic_json<nlohmann::fifo_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<nlohmann::fifo_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>>::operator [](const Key &)'
              with
              [
                  T=nlohmann::basic_json<nlohmann::fifo_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>,
                  StringType=std::string,
                  Key=std::string
              ]
      D:\Dev\include\nlohmann/json.hpp(3130): note: see reference to function template instantiation 'T &nlohmann::fifo_map<StringType,T,nlohmann::basic_json<nlohmann::fifo_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<nlohmann::fifo_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>>::operator [](const Key &)' being compiled
              with
              [
                  T=nlohmann::basic_json<nlohmann::fifo_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>,
                  StringType=std::string,
                  Key=std::string
              ]
      D:\Dev\include\nlohmann/json.hpp(15909): note: see reference to class template instantiation 'nlohmann::fifo_map<StringType,nlohmann::basic_json<nlohmann::fifo_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>,nlohmann::basic_json<nlohmann::fifo_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<nlohmann::fifo_map,std::vector,StringType,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>>>' being compiled
              with
              [
                  StringType=std::string
              ]
      ..\..\hmdq\hmdq.cpp(50): note: see reference to class template instantiation 'nlohmann::basic_json<nlohmann::fifo_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>' being compiled
      ninja: build stopped: subcommand failed.
    

    I wonder, was it resolved, or is it a know bug? If the latter, is there any other solution?

  16. Daniel599 commented on Jul 20, 2019

    @Daniel599
    Contributor

    @risa2000 it doesn't seems like you used my workaround.
    please define your json type as the example below.

    As I said before in my previous comment, there is a way to do it without a change in the libraries, it's a workaround which I don't like that much since it will break if the API will change.
    anyway here it's: (be warn - this workaround will break if the template parameters will change)

    #include "json.hpp"
    #include "fifo_map.hpp"
    #include <iostream>
    
    using namespace nlohmann;
    
    // A workaround to give to use fifo_map as map, we are just ignoring the 'less' compare
    template<class K, class V, class dummy_compare, class A>
    using my_workaround_fifo_map = fifo_map<K, V, fifo_map_compare<K>, A>;
    using my_json = basic_json<my_workaround_fifo_map>;
    
    int main()
    {
    	my_json j;
    	j["f"] = 5;
    	j["a"] = 2;
    	my_json j2 = {
    	  {"pi", 3.141},
    	  {"happy", true},
    	  {"name", "Niels"},
    	  {"nothing", nullptr},
    	  {"answer", {
    	    {"everything", 42}
    	  }},
    	  {"list", {1, 0, 2}},
    	  {"object", {
    	    {"currency", "USD"},
    	    {"value", 42.99}
    	  }}
    	};
    
    	std::cout << j << std::endl;
    	std::cout << j2 << std::endl;
    
    	return 0;
    }

    output:

    {"f":5,"a":2}
    {"pi":3.141,"happy":true,"name":"Niels","nothing":null,"answer":{"everything":42},"list":[1,0,2],"object":{"currency":"U
    SD","value":42.99}}
    

    I don't like this workaround very much since it isn't clean and really patchy, but maybe this will give others a better idea about what to do.

  17. risa2000 commented on Jul 20, 2019

    @risa2000
    Contributor

    @Daniel599 thanks for the nudge. Indeed I did not apply the "fix" as I did not understand that it was one! After following your example, it works as expected. Unfortunately, it turned out that I am stuck anyway.

    The reason is that I am using xtensor library in the same project, which implements also a serialization/deserialization through nlohmann::json, but this library seems to be "hardcoding" nlohmann::json as the type it uses everywhere, with no template for possible specialization with a custom mapping class. So I guess I am going to write another report over there.

  18. theresa95 commented on Apr 1, 2020

    @theresa95

    hey @nlohmann and @Daniel599 !

    I am currently trying to generate JSON with ordered keys and therefore used the workaround method from @Daniel599 . I just copy-pasted your workaround code and it worked as aspected. However, if I try to use it within my base and derived classes, I get an error which I do not really understand. It seems like it fails to call the to_Json methods (because the error appears if I try to map a DerivedClass-instance (test and test2) to my_json.

    I have already tried the example without ordered keys (just by using json = nlohmann::json;) and it works completely fine. The keys in the output are sorted alphabetically and looks like this:

    {
      "cbor": "cbortest",
      "diagnostic": "diagnose: corona",
      "header": {
        "headerId": 3,
        "timestamp": "2019-12-10T16:04:00.00Z",
        "version": "4.0.0"
      },
      "hex": "00f2",
      "roundtrip": true
    }
    

    What I am trying to achieve through using the nlohmann fifo_map is to keep the insertion order and the final output therefore should look like this:

    {
      "header": {
        "headerId": 3,
        "timestamp": "2019-12-10T16:04:00.00Z",
        "version": "4.0.0"
      },
      "cbor": "cbortest",
      "hex": "00f2",
      "roundtrip": true,
      "diagnostic": "diagnose: corona"
    }
    

    Executing the following code outputs two errors:

    Error C2440: 'initializing': cannot convert from 'BaseNamespace::SubNamespace::DerivedClass' to 'nlohmann::basic_json<my_workaround_fifo_map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>'	; in file: main.cpp
    

    image

    Please have a look at the following code:

    In BaseClass.h:

    #ifndef BASECLASS_H
    #define BASECLASS_H
    
    #include <stdint.h>
    #include <string>
    #include "nlohmann/json.hpp"
    #include "fifo_map.hpp"
    
    namespace BaseNamespace{
    
    	namespace SubNamespace{
    
    		class BaseClass {
    		public:
    			BaseClass () {};
    			virtual ~BaseClass () {};
    
    			uint32_t getHeaderId() const { return headerId; };
    			std::string getTimestamp() const { return timestamp; };
    			std::string getVersion() const { return version; };
    
    			void setHeaderId(uint32_t str) { headerId = str; };
    			void setTimestamp(std::string str) { timestamp = str; };
    			void setVersion(std::string bo) { version = bo; };
    
    			void setHeader(UAgvHeader const& header) {
    				setHeaderId(header.getHeaderId());
    				setTimestamp(header.getTimestamp());
    				setVersion(header.getVersion());
    			}
    
    		private:
    			uint32_t    headerId;       
    			std::string timestamp;     
    			std::string version;        
    		};
    
    		// A workaround to give to use fifo_map as map, we are just ignoring the 'less' compare
    		using namespace nlohmann;
    		template<class K, class V, class dummy_compare, class A>
    		using my_workaround_fifo_map = fifo_map<K, V, fifo_map_compare<K>, A>;
    		using my_json = basic_json<my_workaround_fifo_map>;
    
    		void to_json(my_json &j, const BaseClass &p)
    		{			
    			j = my_json{
    				{ "headerId", p.getHeaderId() }, 
    				{ "timestamp", p.getTimestamp() }, 
    				{ "version", p.getVersion() }
    			};
    		}
    
    		void from_json(const my_json &j, BaseClass &p)
    		{
    			p.setHeaderId(j.at("headerId").get< std::uint32_t>());
    			p.setTimestamp(j.at("timestamp").get< std::string >());
    			p.setVersion(j.at("version").get<std::string>());
    		}
    
    	} // namespace SubNamespace
    
    } // namespace BaseNamespace
    
    #endif // BASECLASS_H_
    

    In DerivedClass.h:

    #ifndef DERIVEDCLASS_H
    #define DERIVEDCLASS_H
    
    #include <stdint.h>
    #include <string>
    #include "nlohmann/json.hpp"
    #include <optional>
    #include "BaseClass.h"
    
    namespace BaseNamespace{
    
    	namespace SubNamespace{
    
    		class DerivedClass : public BaseClass {
    		public:
    
    			std::string getCBor() const { return cbor; };
    			std::string getHex() const { return hex; };
    			bool getRoundtrip() const { return roundtrip; };
    			std::optional<std::string> getDiagnostic() const { return diagnostic; };
    
    			void setCBor(std::string str) { cbor = str; };
    			void setHex(std::string str) { hex = str; };
    			void setRoundtrip(bool bo) { roundtrip = bo; };
    			void setDiagnostic(std::optional<std::string> opt_str) { diagnostic = opt_str; };
    
    		private:
    			std::string cbor;
    			std::string hex;
    			bool        roundtrip;
    			std::optional<std::string> diagnostic = std::nullopt;
    		};
    		
    		void to_json(my_json &j, const DerivedClass& p)
    		{
    			j["header"] = static_cast<BaseClass>(p);
    			j["cbor"] = p.getCBor();
    			j["hex"] = p.getHex();
    			j["roundtrip"] = p.getRoundtrip();
    
    			// assuming you only want a "diagnostic" key if there is an actual value;
    			// if not, store a nullptr and adjust the from_json accordingly
    			if (p.getDiagnostic() != std::nullopt)
    			{
    				j["diagnostic"] = p.getDiagnostic().value();
    			}
    		}
    
    		void from_json(const my_json &j, DerivedClass&p)
    		{
    			p.setHeader(j.at("header").get<BaseClass>());
    			p.setCBor(j.at("cbor").get< std::string >());
    			p.setHex(j.at("hex").get< std::string >());
    			p.setRoundtrip(j.at("roundtrip").get< bool >());
    
    			// if we also allow "null" values, then we need to add an "is_string()"
    			// check
    			if (j.count("diagnostic") != 0)
    			{
    				p.setDiagnostic(j.at("diagnostic").get< std::string >());
    			}
    		}
    
    	} // namespace SubNamespace
    
    } // namespace BaseNamespace
    
    #endif // DERIVEDCLASS_H
    

    In main.cpp:

    #include <iostream>
    #include <string>
    #include <nlohmann/json.hpp>
    #include <iomanip> 
    #include <optional>
    #include "DerivedClass.h"
    
    using namespace nlohmann;
    // A workaround to give to use fifo_map as map, we are just ignoring the 'less' compare
    template<class K, class V, class dummy_compare, class A>
    using my_workaround_fifo_map = fifo_map<K, V, fifo_map_compare<K>, A>;
    using my_json = basic_json<my_workaround_fifo_map>;
    
    int main(int argc, char* argv[]) {
    
    	BaseNamespace::SubNamespace::DerivedClass test;
    	test.setHeaderId(3);
    	test.setTimestamp("2019-12-10T16:04:00.00Z");
    	test.setVersion("4.0.0");
    	test.setCBor("cbortest");
    	test.setHex("00f2");
    	test.setRoundtrip(true);
    	test.setDiagnostic("diagnose: corona");
    	my_json j = test;                                  // ERROR: no suitable conversion
    	std::cout << std::setw(2) << j << std::endl;
    
    	std::string str = R"({"header":
            {   "headerId" : 4711,
                "timestamp" : "1 Uhr",
    		"version" : "5.0.0" 
            },
            "cbor" : "+X4A",
            "hex" : "f97e00",
            "roundtrip" : true,
            "diagnostic" : "NaN"
            })";
    
    	my_json j2 = my_json::parse(str);
    	BaseNamespace::SubNamespace::DerivedClass test2 = j2;
    	my_json k = test2;                                 // ERROR: no suitable conversion
    
    	std::cout << std::setw(2) << k << std::endl;
    
    
    	return 0;
    }
    
  19. Daniel599 commented on Apr 1, 2020

    @Daniel599
    Contributor

    Hi @theresa95, after some investigation I found out the cause of your error is due to multiple "my_json" types: one inside BaseNamespace::SubNamespace::my_json and the other in the global scope.
    I don't know if it's the same case in your original code, but I mange to fix it by doing the following:

    • remove using namespace nlohmann; within your namespace (e.g inside BaseClass.h & DerivedClass.h)
    • define my_json in single place at BaseClass.h
      after doing the steps above, your code example compiles on g++ 7.5 with -std=c++17, I hope it compiles on windows as well (if not let me know)
  20. theresa95 commented on Apr 1, 2020

    @theresa95

    Hey @Daniel599 , first of all, thank you for the quick answer!

    I edited the codesnippet of my question to fit your answer.
    I removed the following lines from the DerivedClass.h file:

    using namespace nlohmann;
    template<class K, class V, class dummy_compare, class A>
    using my_workaround_fifo_map = fifo_map<K, V, fifo_map_compare<K>, A>;
    using my_json = basic_json<my_workaround_fifo_map>;
    

    But I still get the same error messages in the main.cpp file:
    image

    Removing the "using namespace nlohmann" in the BaseClass.h file results in other errors so I have left it there:
    image

    What should I do with my_json definition and using namespace nlohmann in the main.cpp file?

    Thank you so much for your help in advance!

  21. Daniel599 commented on Apr 1, 2020

    @Daniel599
    Contributor

    @theresa95
    in BaseClass.h:

    namespace BaseNamespace{
    	namespace SubNamespace{
    // Other code
    		// A workaround to give to use fifo_map as map, we are just ignoring the 'less' compare
    		template<class K, class V, class dummy_compare, class A>
    		using my_workaround_fifo_map = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>;
    		using my_json = nlohmann::basic_json<my_workaround_fifo_map>;
    	}
    }
    

    note the addition of nlohmann:: which is needed when you remove the using namespace nlohmann

    in main.cpp:

    • you can keep the using namespace nlohmann but I would recommend against it, prefer to use nlohmann::blabla whenever you need (P.S I don't think you need it in main anymore anyway)
    • replace my_json with BaseNamespace::SubNamespace::my_json

    a bit more details:
    since my_json is declared inside the namespace BaseNamespace::SubNamespace and main isn't (it's in the global scope), you have two options: add the namespace prefix or add using namespace BaseNamespace::SubNamespace in main.cpp, I like more the first option since it's more explicit about where things are taken from.

  22. theresa95 commented on Apr 1, 2020

    @theresa95

    @Daniel599 That did the trick! Thank you so much!

  23. nlohmann commented on Jul 30, 2021

    @nlohmann
    Owner

    @ccpearson Thanks for sharing. I am confused - is fifo_map broken with the latest release? We use object_comparator_t now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions