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

no matching function for call to ‘nlohmann::basic_json<>::basic_json(<brace-enclosed initializer list>)’ #2559

Closed
deepakd82 opened this issue Dec 30, 2020 · 15 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@deepakd82
Copy link

deepakd82 commented Dec 30, 2020

Hi Team,

I am trying to convert json to managed object and in this regard, I am using the to_json and from_json functions provided by nlohmann/json.
When I write a sample program, I am able to see no issues with this APIs but when I integrate with the actual project, observing the below error when i call get_to with int as datatype.

no matching function for call to ‘nlohmann::basic_json<>::basic_json()’

CPP file (MTop.cpp)

void MTop::to_json(json& j, const MTop& mo)
{
    j = json{{"OClass", mOClass}};
}

void MTop::from_json(const json& j, MTop& mo)
{
    mo.mOClass = j.at("OClass").get_to< int >();   ---> This line is showing compilation error.
}

Headerfile (MTop.hpp)

#include <MObjectCls.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

class MTop : public MObjectCls
{
   public:
       
     virtual void to_json(json& j, const MTop& mo);

     virtual void from_json(const json& j, MTop& mo);

   private:
  
     MObjectCls mOClass;
};

Headerfile (MObjectCls.h)

class MObjectCls
{
   public: 
   
   MObjectCls(int value);
};

Since there to_json and from_json are used by the object of this class only, these two functions are not maintained under any namespace.

if the from_json( ) logic is modified as below -

j.at("OClass").get_to(mo.mOClass);

MTop.cpp -->

error: no matching function for call to ‘nlohmann::basic_json<>::basic_json(<brace-enclosed initializer list>)’
error: no matching function for call to ‘nlohmann::basic_json<>::get_to(MObjectCls&) const’
../include/nlohmann/json.hpp:3017:28: error: no type named ‘type’ in ‘struct std::enable_if<false, int>’
../include/nlohmann/json.hpp:3030:25: error: no type named ‘type’ in ‘struct std::enable_if<false, int>’

Please guide me what could be the issue.

Note: Since the header and cpp files are big, I have shared only the contents which are of focus here.

  • Deepak
@nlohmann
Copy link
Owner

The functions from_json and to_json must be defined in the same namespace as the type. They must not be member functions. Please try moving them out of MTop.

@deepakd82
Copy link
Author

deepakd82 commented Dec 31, 2020

@nlohmann
Thanks for your response.

I have modified the files as below -

MTop.cpp

#include <nlohmann/json.hpp>
using json = nlohmann::json;

namespace MTop_ns
{
    typedef enum
    {
        STATE_LOCKED = 0,
        STATE_UNLOCKED = 1,
        STATE_SHUTTINGDOWN = 2
    } MAdminStateEnum;

    NLOHMANN_JSON_SERIALIZE_ENUM ( MAdminStateEnum, {
        {STATE_LOCKED, "locked"},
        {STATE_UNLOCKED, "unlocked"},
        {STATE_SHUTTINGDOWN, "shutdown"},
    });

    struct MTop000
    {
        int                         mOInstId;
        std::string                 mOInstName;
        MAdminStateEnum  mAdminState;
    };

    void to_json(json& j, const MTop000& mo)
    {
        j = json{{"mOInstId", mo.mOInstId},
                 {"mOInstName", mo.mOInstName},
                };
    }

    void from_json(const json& j, MTop000& mo)
    {
        j.at("mOInstId").get_to(mo.mOInstId);
        j.at("mOInstName").get_to(mo.mOInstName);
    }
}

MTop.hpp

#include <MObjectCls.h>

class MTop : public MObjectCls
{
   public:
       
   private:
  
     MObjectCls mOClass;
};

Now, I don't see any compilation errors as the from_json and to_json are not part of the member functions.
I would be accessing this as below in other file -

MTop_ns::MTop000 mT = {"10, "mTopClass", STATE_LOCKED"};
json j = mT;

Since I have multiple managed objects, there will be many class files. If I had to write to_json/from_json for all those, then I need to do the same for all right ?
Is there any other way to do it ?

  • Deepak

@nlohmann
Copy link
Owner

Yes, you have to define it for every type. Maybe this article helps: https://json.nlohmann.me/features/arbitrary_types/#simplify-your-life-with-macros

@nlohmann nlohmann added kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation labels Dec 31, 2020
@deepakd82
Copy link
Author

deepakd82 commented Dec 31, 2020

@nlohmann
Thanks for the reference.

Looking into that, I made changes to my code and here is the change -

Headerfile (MTop.hpp)

#include <MObjectCls.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

namespace MTop_ns
{
class MTop : public MObjectCls
{
   public:
       
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(MTop, moClass)

   private:
  
     MObjectCls mOClass;
};
}

Headerfile (MObjectCls.h)

class MObjectCls
{
   public: 
   
   MObjectCls( );

   MObjectCls(int value);

   virtual ~MObjectCls( );
};

WIth this, I am observing below errors -

MTop.h->
error: no match for ‘operator=’ (operand types are ‘nlohmann::basic_json<>::value_type’ {aka ‘nlohmann::basic_json<>’} and ‘const mOClass’)
../include/nlohmann/detail/macro_scope.hpp:268:81: error: no matching function for call to ‘nlohmann::basic_json<>::get_to(MObjectCls&) const’
../include/nlohmann/json.hpp:3017:28: error: no type named ‘type’ in ‘struct std::enable_if<false, int>’

If I modify as below, then I don't see any error.

Headerfile (MTop.hpp)

#include <MObjectCls.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

namespace MTop_ns
{
class MTop : public MObject
{
   public:
       
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(MTop, moClass)

   private:
  
     int mOClass;
};
}

This is a nested class where we need to access parameters from base class..

Should this macro be called inside all the inherited classes with the namespace ?

  • Deepak

@nlohmann
Copy link
Owner

nlohmann commented Jan 1, 2021

Yes.

@deepakd82
Copy link
Author

deepakd82 commented Jan 7, 2021

@nlohmann
Thanks for your continuous support.

According to the document, we see that if the macro NLOHMANN_DEFINE_TYPE_INTRUSIVE is used, there is no need to define the macro within the namespace. Currently, I am following the same. Is this correct ?

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...) is to be defined inside of the namespace of the class/struct to create code for.
NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...) is to be defined inside of the class/struct to create code for. This macro can also access private members.

#include <MObjectCls.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

class MTop : public MObjectCls
{
   public:
       
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(MTop, moClass)

   private:
  
     int mOClass;
};
MTop.h:  error: invalid use of non-static data member ‘MTop::mOClass’
../include/nlohmann/detail/macro_scope.hpp:276:130: error: ‘NLOHMANN_JSON_TO’ was not declared in this scope
../include/nlohmann/detail/macro_scope.hpp:277:132: error: ‘NLOHMANN_JSON_FROM’ was not declared in this scope

To resolve the non-static data member error, I moved the private section of the class ahead of public. But that didn't helped.

Are these errors related with not using namespace ?

  • Deepak

@nlohmann
Copy link
Owner

nlohmann commented Jan 7, 2021

Looks like a typo. In NLOHMANN_DEFINE_TYPE_INTRUSIVE, you write moClass (lower-case o), but the member is called mOClass (upper-case O).

@deepakd82
Copy link
Author

@nlohmann
My apology. The code which was pasted had this typo error.
In the code what is being used, the variable passed is mOClass only.

NLOHMANN_DEFINE_TYPE_INTRUSIVE(MTop, mOClass)

Need your inputs on my below query -

According to the document, we see that if the macro NLOHMANN_DEFINE_TYPE_INTRUSIVE is used, there is no need to define the macro within the namespace. Currently, I am following the same. Is this correct ?

  • Deepak

@gregmarr
Copy link
Contributor

gregmarr commented Jan 7, 2021

What compiler are you using? Looks like there's a problem with the macro expansion.

@gregmarr
Copy link
Contributor

gregmarr commented Jan 7, 2021

Can you try replacing that macro with this?

friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { 
    NLOHMANN_JSON_TO(mOClass)
}
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) {
    NLOHMANN_JSON_FROM(mOClass)
}

If that doesn't work, then try this:

friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { 
    nlohmann_json_j["mOClass"] = nlohmann_json_t.mOClass;
}
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) {
    nlohmann_json_j.at("mOClass").get_to(nlohmann_json_t.mOClass);
}

This will at least narrow down the failure.

@deepakd82
Copy link
Author

@gregmarr

Thanks for your inputs.
Will modify as suggested and check.

  • Deepak

@deepakd82
Copy link
Author

@gregmarr
Forgot to share the compiler details.
I am using WSL2 (running Ubuntu 20.4)

$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ uname -a
Linux IN-9KHT253 4.19.128-microsoft-standard #1 SMP Tue Jun 23 12:58:10 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

@deepakd82
Copy link
Author

deepakd82 commented Jan 8, 2021

@gregmarr

I tried your suggestion but end up getting different error

MTop.hpp

#include <MObjectCls.h>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

class MTop : public MObjectCls
{
public:

friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { 
           nlohmann_json_j["mOClass"] = nlohmann_json_t.mOClass;  
}
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) {
           nlohmann_json_j.at("mOClass").get_to(nlohmann_json_t.mOClass);
}

private:

 MObjectCls mOClass;

};

MObjectCls.h

class MObjectCls
{
public:

MObjectCls( );

MObjectCls(int value);

virtual ~MObjectCls( );
};

Below error is observed -

  1. error: ‘Type’ does not name a type
  2. error: ‘Type’ has not been declared
  3. error: request for member ‘mOClass’ in ‘nlohmann_json_t’, which is of non-class type ‘const int’
  4. error: redefinition of ‘void to_json(nlohmann::json&, const int&)’

mOClass is integer. Its Unsigned integer. It should be supported by JSON API right ?

  • Deepak

@gregmarr
Copy link
Contributor

gregmarr commented Jan 12, 2021

Right, I forgot to change Type to the type of mOClass.

@deepakd82
Copy link
Author

@gregmarr
Thanks for the clarification.

This resolved the compilation error.. Hopefully, I should be able to integrate successfully.
Thanks for your support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

3 participants