I have written code for a controller that has buttons and lamps. It is based on Arduino/ATmega2560. RAM is very limited. Changing to another device is no option.
Each button and lamp is modelled as a C++ class instance. They are derived from an abstract class Thing, which contains a pointer mpTarget that indicates connections between Things. The targets are initially assigned at runtime and do not change during runtime.
I need to save memory. As I have ~600 Things, it would help me alot if all those mpTargets were stored in ROM (and not in RAM), because the targets are known at compile time.
So I played with constexpr. However, it seems to be impossible to make a class only partially constexpr. I cannot make the whole class constexpr, because there are also member variables that change during runtime (mState in the example below).
What would be a good way to achieve this behavior? constexpr? Templates? Anything?
Clarifications
I know that
mpTargetis currently initialized at runtime. But each target is known at compile time, that's why I'd like to find a good way to save RAM bytes of these pointers.I don't really want to move away from object oriented design. I used an approach with simple, "plain old" datatypes before (which actually consumed less RAM). But as development of this code is still ongoing (classes and instances are added/deleted/modified), there is a high chance to miss necessary modifications, introducing hard-to-find bugs.
For this project, it would be more than enough to save the RAM storage only for
mpTarget. Keeping the overhead of vtable pointers is fine. What I'm actually looking for is - as the title suggests - a way how we could implement a class whose members are partiallyconstexpr. I also thought about using templates, but without success.
Sample code
#include <iostream>
class Thing
{
public:
// only called in setup()
void setTarget(Thing & pTarget)
{
mpTarget = & pTarget;
}
virtual void doSomething(int value) {};
protected:
// known at compile time - can we make this constexpr?
Thing * mpTarget;
};
class Button : public Thing
{
public:
void setState(int newState)
{
mState = mState + newState;
mpTarget->doSomething(mState);
}
private:
// changes during runtime
int mState;
};
class Lamp: public Thing
{
public:
virtual void doSomething(int value)
{
std::cout << value << std::endl;
};
};
Button myButton;
Lamp myLamp;
int main()
{
myButton.setTarget(myLamp);
while (1)
{
myButton.setState(123);
}
}