Is it somehow possible for a class to act as a proxy when accessing it's members? The simplest way would be of course to write getters/setters but this is inflexible und unelegant since you have to write all of the setters yourself which bloats the code up.
The problem is that I want to abstract away the fact that some data lies in the progmem of the microcontroller. Basically I want that
MemberType member = object->member; // won't work if object lies in progmem
to be translated to something like
MemberType member; // Allocate memory in RAM for the member
memcpy_P(&member,
&object->member, // assuming that this gives a valid pointer to the member
sizeof(MemberType));
In embedded C one can use the address space __flash
to do something like that. Unfortunately C++ does not support this.
So I thought about overloading operator->()
. Unfortunately operator->()
does not get any information which member you are gonna access (btw: why wtf? The sole purpose of -> is to access a member so why should anybody want to throw this information away?). .
can't be overridden at all.
Has anybody an idea how to solve that problem? The syntax does not have to be ->
of course. If it is possible with some esoteric template construct I would be happy as well. I don't know enough C++ maybe is is not possible at all. C++ seems to be a bit inflexible on the meta-programming side.
Edit: After the inspiration from the answer I now decided to use a wrapper class and override the cast operator.
template<typename Type>
class InProgmem {
Type const self; // InProgmem<Type> should be as big as Type
InProgmem(Type val) : self(val) {} // Keep the compiler quiet
public:
operator Type() const {
Type out;
memcpy_P(&out, this, sizeof(Type));
return out;
}
} __attribute__((packed));
// Example use:
PROGMEM prog_uchar foo = 14;
class Test {
public:
InProgmem<unsigned char> bar;
};
Test *baz = (Test*)&foo;
unsigned char bar = baz->bar;
You could create a new class ProgmemMemberType
and define some assignment operators to convert between memory spaces.
const MemberType &MemberType::operator=(const ProgmemMemberType &other)
{
memcpy_P(this,
other.progMemPointer(),
sizeof(MemberType));
return *this;
}
const ProgmemMemberType &ProgmemMemberType::operator=(const MemberType &other)
{
// Whatever the reverse of memcpy_P is...
return *this;
}
Then you can write MemberType member = object->member
or object->member = member
and the assignment operator will do the work.
This is the cleanest solution I can think of; the ->
operator is not really meant for this kind of thing.
And of course if you don't want to define a new wrapper class for every type you use, you can use a template class.