I have a template class which takes as its first template argument a foo * pointer. I'd like to instantiate one of these with a foo located at an absolute address, like so:
class foo
{
int baz;
};
template<foo *f> class bar
{
public:
bar() {}
void update() { /* ... */ }
};
// ....
#define FOO_ADDR ((foo *)0x80103400)
#define FOO_NULL ((foo *)0)
foo testFoo;
bar<FOO_ADDR> myFoo; // fails with non-integral argument
bar<FOO_NULL> huh; // compiles, I was surprised by this
bar<&testFoo> test; // compiles as expected (but not useful)
Does anyone know if it's possible without resorting to the linker and getting FOO_ADDR to be defined with external linkage?
This is with the Keil ARM C/C++ Compiler version V5.06 update 1 (build 61), I've tried switching on C++11 mode but (apart from throwing a load of new errors in the system headers) it didn't change the behaviour.
Update: here's the proposed solution (with the real code this time) using int casts
template<uint32 PORT, uint32 BIT, uint32 RATE> class LedToggle
{
uint32 mTicks;
uint32 mSetReset;
public:
LedToggle()
{
mTicks = 0;
mSetReset = 1 << BIT;
}
void Update()
{
uint32 mask = ((mTicks++ & RATE) - 1) >> 31;
((GPIO_TypeDef *)PORT)->BSRR = mSetReset & mask;
mSetReset ^= ((1 << BIT) | (1 << (BIT + 16))) & mask;
}
};
LedToggle<(uint32)GPIOC, 13, 1023> led;
It's pretty ugly, but it does work. I'd be interested to hear if anyone can improve on it?