0

I'm trying to reduce boilerplate class definitions, while also making it easy for me to change them in the future without having to go back and updating all of them manually

I'm wondering if I just need to make a script to generate these classes or if I can actually accomplish it all with variadic macros

I'd like to do this without Boost if possible, but if needed I can pull in and learn Boost

The goal is to be able to create an editor for all Entity Stats, which are grouped into "pods" (bunches of stats that go together, like HealthStats, AmmoStats, StorageStats, etc)

This is what I'd like to create about a dozen of:

class _EntityStorageInfo : public EntityStatPod
{
public:
    _EntityStorageInfo() :EntityStatPod("_EntityStorageInfo"),
        Ammo("Ammo"),
        Water("Water"),
        Oil("Oil"),
        Nanites("Nanites")
    {};

    void draw()
    {
        drawStats(Ammo, Water, Nanites, Oil);
    }

    EntityStat<int> Ammo;
    EntityStat<double> Water;
    EntityStat<double> Nanites;
    EntityStat<double> Oil;

private:
    friend cereal::access;
    template<class Archive>
    void serialize(Archive& archive, std::uint32_t const version)
    {
        archive(cereal::base_class<EntityStatPod>(this), health, globalID, three, four);
    }

};

This is as far as I've gotten myself, but I feel like there's one last step I'm missing that could let me skip having to supply the words "ammo,water,nanites,oil" multiple times

#define ENTITYSTATPODCLASS_BEGIN(name)      \
class name : public EntityStatPod           \
{                                           \
    public: name():EntityStatPod("name"),   


#define ENTITYSTATPODCLASS_MIDDLE(...)      \
    {};                                     \
    void draw() { drawStats( __VA_ARGS__);}

#define ENTITYSTATPODCLASS_END(...)         \
    private:                                                      \
    friend cereal::access;                                        \
    template<class Archive>                                       \
    void serialize(Archive& archive, std::uint32_t const version) \
    {                                                             \
        archive(cereal::base_class<EntityStatPod>(this), __VA_ARGS__);\
    }                                                             \
                                                                  \
};  

                                                          \

and this is how it looks using the macros:

ENTITYSTATPODCLASS_BEGIN(_EntityStorageInfo)
                Ammo("Ammo"),
                Water("Water"),
                Nanites("Nanites"),
                Oil("Oil")

ENTITYSTATPODCLASS_MIDDLE(Ammo,Water,Nanites,Oil)

EntityStat<int>    Ammo;
EntityStat<double> Water;
EntityStat<double> Nanites;
EntityStat<double> Oil;

ENTITYSTATPODCLASS_END(Ammo, Water, Nanites, Oil)

I'd appreciate any ideas on how I could reduce the boilerplate even further, or if it's even possible without just writing a "class generation" script in another language

Thanks!

  • If all your classes don't have the same members with the same names, I don't see how you can avoid having to specify the names, and types of members for each class. – cigien Jul 18 '20 at 17:30
  • Yes they would all have different numbers of different types of variables – Mike Dawson Jul 18 '20 at 17:34
  • The macro hardly seems to be reducing the boilerplate. How many more lines of code would you need to write without the macro? – cigien Jul 18 '20 at 17:36
  • I plan on expanding the class over time, and each time I do I don't want to go back and re-write all of them – Mike Dawson Jul 18 '20 at 17:38
  • Maybe you could have a base class with common functionality that all your classes inherit from. Then you would only have to do the modifications in one place. – cigien Jul 18 '20 at 17:39
  • Don't use macros. There are many alternatives. It seems a template class is what you look for ... – OrenIshShalom Jul 18 '20 at 17:48
  • @OrenIshShalom I use class templates for EntityStat , and use variadic function templates for drawStats , but I don't see how I could use a class template to accomplish this since I won't know how many or what type of member EntityStat variables each class would have – Mike Dawson Jul 18 '20 at 17:51
  • Unclear what you're trying to achieve ... – OrenIshShalom Jul 18 '20 at 17:55
  • "I don't see how I could use a class template to accomplish this since I won't know how many or what type of member EntityStat variables each class would have" Exactly for this purpose variadic templates are made for. – Klaus Jul 18 '20 at 19:13
  • `ENTITYSTATPODCLASS_BEGIN` and `ENTITYSTATPODCLASS_END` are _incredibly_ confusing for any IDE and code analysis tools you are going to use. Every developer will be enraged that there is not clearly class definition visible, the resulting code will be unreadable and unmaintainable. You will not be able to use "jump to definitions" functions from IDE, compiler errors will be utterly confusing. Strongly consider just writing it out. – KamilCuk Aug 03 '22 at 13:42

0 Answers0