But my question is, can I tell from a variables address where it lives? It would seem intuitively so. Surely PROGMEM addresses are different from SRAM addresses right?
No. They are two pieces of memory. Therefore there is an address 100 in each of them. It isn't the same piece broken into different bits, with different addresses.
If the following worked, you might have done it with function overloading:
void print (char * bar);
void print (prog_char * bar);
}; // end of foo
But it doesn't. It gives:
sketch_dec13a:7: error: 'void foo::print(prog_char*)' cannot be overloaded
sketch_dec13a:6: error: with 'void foo::print(char*)'
Program memory is an attribute, not a type. Therefore C++ doesn't let you overload on an attribute alone.
I think you need a different design. Storing the addresses of two different sorts of things in one place is asking for trouble.
However you *might* find in practice that SRAM addresses are lower than PROGMEM ones. Simply because you only have 2Kb of SRAM, and 32 Kb of PROGMEM. Now if the compiler happens to put PROGMEM strings into addresses above 2Kb then a simple address test could work (in other words, if they go above the code). But if the compiler puts them into PROGMEM first (and then follows them by the instruction code) then they both may end up in addresses which are in the range 0 to 2 Kb.
You might get away with a flag, eg. set the 0x8000 bit on SRAM addresses, and then check that in your function (and mask it out of course). The viability of that depends on how your code works, and why you are trying to mix the two sorts of addresses in the first place.