But this is not the counter-example. Member pointers are not
"pointers" in this regard. They're more like smart offsets,
just employing the pointer *notation* like iterators and smart
pointers do, neither of which are necessarily pointers.
I'm not sure about the syntax business. Normal pointers don't
use the ->* or .* operators, and the * operator (nor any pointer
arithmetic) won't work with pointers to members. They're
definitely different beasts from regular pointers.
Like in some other cases, the standard isn't really consistent
here; sometimes, they're called pointers, but in other cases,
when the standard says pointer, they aren't included.
The single counter example is instead pointers to routines.
E.g. a 'void (*)()' can not be cast to 'void*' in standard
C++, because in standard C++ code and data live in two
logically separate address spaces.
I'm not sure what you mean by separate address spaces. What is
sure is that they can, and in some implementions do have
different representations: I've used systems where pointers to
functions are 32 bits, but pointers to data 16, and vice versa.
Posix adds the guarantee that on a Posix conformant system, the
to do have the same representation (although I've worked on
pre-Posix Unix where this wasn't the case). So while you can't
(yet---C++0x makes it "conditionally" legal) directly convert a
void* to a void (*)() (a compiler diagnostic is required in
pre-0x C++), you can do things like:
void (*pf)() ;
*reinterpret_cast< void** >( &pf ) = dlsym( ... ) ;
.. (See dlsym in the Posix standard.)
Note that Windows has the opposite problem---if your dll
contains data, you have to use something like:
void* p ;
*reinterpret_cast< FARPTR* >( &p ) == GetProcAddress(...) ;
or something similar. (I can't find anything that guarantees
that this must work, but in practice, I think it's safe.)