2

I have a code similar to the following:

template<class ObjType>
class jsonable
{
 private:
    static map<string, jsonElem> config;
 protected:
    virtual void setConfig() = 0;
 //other fields and methods in public/private
}

class user : public jsonable<user>
{
 protected:
    virtual void setConfig();
 //other fields and methods in public/private
}

class client : user
{
 protected:
    virtual void setConfig() {user::setConfig(); /* more config */}
 //other fields and methods in public/private
}

The main idea of this code is to save in static variables data related to the class referenced in the template. The problem comes when I want to inherit from the user class: the static variable is shared between user and client classes, instead of one static variable for each class.

I've tried to do something like:

class client : user, jsonable<client>

But a bunch of problems appeared (many methods with same name, and some other related to inherit 2 times the same class). I don't know if there is an elegant way of do this, or even if there is a way at all. (I'm a bit newbie in c++)

Any idea would be welcome! :). And of course, I can "copy" all the contents of user into client but... I would like to do not do that until there are no more options.

Edit: In order to add context and details to the question, I'm going to explain a bit what I'm doing (or want to do). Jsonable is a class that provides the ability to serialize into Json another class (helped by https://github.com/nlohmann/json).

To achive this, it uses a static map to store each jsonable-field name and its info (type and position relative to the start of the class in memory, so it can be serialized and deserialized).

The problem comes if a class inherits from another class that inherits from jsonable. Both shares that map, so only the baseclass data is consider when serializing/deserializing. Hope this explanation helps to understand...

Edit2: Giving a full code in a question seems very overkilling to me. If someone wants something to compile, I've uploaded a git repo: https://github.com/HandBe/jsontests Really thanks to all the people who have put interest on this question!.

Ralequi
  • 306
  • 2
  • 12
  • 1
    Maybe a dupe, maybe not, but worth a read all the same: [How can I avoid the Diamond of Death when using multiple inheritance?](http://stackoverflow.com/questions/137282/how-can-i-avoid-the-diamond-of-death-when-using-multiple-inheritance) – user4581301 Aug 08 '16 at 17:45
  • 1
    It would be easier to answer this question, if you explained what the desired behavior of your classes/subclasses is. – midor Aug 08 '16 at 17:49
  • Why do you want `client` to be a jsonable client when it's already a jsonable user through `user` ? – Ceros Aug 08 '16 at 17:50
  • Thank you guys, i added an small explanation to the question so it the problem can be more understable. Hope I hope not to bore anyone. @user4581301 i'm going to check it and virtual inheritage, thanks! – Ralequi Aug 08 '16 at 18:01
  • 1
    If you can implement `user` without deriving from `jsonable`, it will be easy to resolve your problem. – R Sahu Aug 08 '16 at 18:08
  • 2
    Please make sure you don't forget the virtual ~dtors in your actual code. – kfsone Aug 08 '16 at 18:10
  • @RSahu Well... that made me think... Is there a way to do something like: `template class user : public json::jsonable` ? First try seems like an infinite description-recursion – Ralequi Aug 08 '16 at 18:15
  • No, that won't work. I was thinking you can use `json::jsonable` in the implementations of the member functions of `use` that depend on the functionality provided by `json:jsonable`. – R Sahu Aug 08 '16 at 18:25
  • 1
    Can't debug invisible code. Please demonstrate a specific problem that can be reproduced by others, as described in [mcve]. – n. m. could be an AI Aug 09 '16 at 11:33
  • 1
    Where do you use `ObjType`? If it's not used, then the whole problem disappears into an abstract discussion of not-happening problems. – grek40 Aug 09 '16 at 11:35
  • I don't see anything wrong with your code though it might result in quite a convoluted interface. I agree with comments above, we need the context in which this code is used. – Patrik H Aug 09 '16 at 11:42
  • First of all, thank you for your interest. I've uploaded to github a full-compilable example of this with one of the modifications suggested bellow. Of course it doesn't work (yet) at runtime, but I expect it could make the context more understable... if not, I don't know how to be more explicit without a big-big question :/ Git repo: https://github.com/HandBe/jsontests – Ralequi Aug 09 '16 at 14:18

2 Answers2

1

A possible solution can be derive client from both user (because it is a user) and jsonable<client> as (private/public apart)

class user : public jsonable<user>
{
 protected:
    virtual void setConfig();
 //other fields and methods in public/private
};

class client: public user, public jsonable<client>
{
   virtual void setConfig()
   {
       user::setConfig();
       // more config, referred to jsonable<client>::map
   }
}

because it has to implement jsonable for itself (regardless of user).

This is the so-called "stacked parallelogram" inhertiance pattern very common in multiple interface implementations as modular behavior.

Now user and client have each their own configuration

Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63
  • I've been working in it for a half-day or so. I'm still on it, since it seems the best option (of course like @grek40 said it doesn't work with virtual inheritance, but i believe something can be done). The actual state with this implementation: https://github.com/HandBe/jsontests – Ralequi Aug 09 '16 at 14:07
  • it finally worked! I've to add many workaround like a new function `virtual void setConfig(map &config)` to pass the static to base class, so base-class can "register" its information inside the upper-class info. Thank you! PD: Probably, i'll make this opensource when it's full-verifyed. Thank you all ~ ! – Ralequi Aug 09 '16 at 15:21
  • 1
    It must NOT work with virtual inheritance: `jasonable` and `jasonable` are distinct things that must not be merged (and cannot be) – Emilio Garavaglia Aug 09 '16 at 16:53
0

If I understand your problem correctly: you want client to be a user, but also have all the per-class statics defined in jsonable?

Have you considered composition over inheritance? This could work either way:

1) make user a component of client

class client : public jsonable<client>
{
    user parent; // could also be a pointer
    void setConfig() {parent.setConfig(); /* more config */}
    /* ... */
}

2) make jsonable a component:

class user
{
    jsonable<user> userjson; // public, private, whatever is appropriate for your design
    /* ... */
}

class client : public user
{
    jsonable<client> clientjson;
    /* ... */
}      
Joris
  • 412
  • 3
  • 8
  • Thank you @Joris. Of course I've considered it, and of course it can be the final option. The problem of this implementation is that i cant create a list of different users. Of course, if i don't find any better option, i would take it! – Ralequi Aug 09 '16 at 14:01