Reputation: 33395
An API uses void*
to store untyped pointer offsets. It's a bit hacky, but okay whatever.
To express my offset arithmetic, I tried doing something like this
int main ()
{
void * foo;
foo = static_cast <int *> (nullptr) + 100;
static_cast <int * &> (foo) += 100;
}
The last line fails to compile (gcc)
x.cpp:7:28: error: invalid static_cast from type ‘void*’ to type ‘int*&’
The fix is simple:
foo = static_cast <int *> (foo) + 100;
But why isn't the first one allowed?
Before you answer "because the standard says so", why does the standard say so? Is the first method somehow dangerous? Or is it just an oversight?
Upvotes: 2
Views: 523
Reputation:
It's not allowed for the same reason that int i; static_cast<long &>(l) = 3L;
isn't allowed.
Sure, on a lot of implementations (where int
and long
have the same size, representation and alignment), it could work. But the rules for which casts are valid are mostly the same for all implementations, and clearly this could never work on platforms where int
and long
have different sizes, meaning it'd be impossible to allow accessing one as the other on those platforms.
Historically, there have been implementations on which void *
and int *
have different representations.
Later, after the standard stating that accessing void *
as if it were an int *
is invalid, implementations also started optimising on the assumption that valid programs do not do that:
void *f (void **ppv, int **ppi) {
void *result = *ppv;
*ppi = nullptr;
return result;
}
The implementation is allowed to optimise this to
void *f (void **ppv, int **ppi) {
*ppi = nullptr;
return *ppv;
}
and such optimisations, when they reduce code size or increase efficiency, are commonplace nowadays. If f
were allowed to be called as void *pv = &pv; f (pv, &static_cast<int*&>(pv));
, this optimisation would be invalid. Because such optimisations have proved useful, the rules are unlikely to change.
Upvotes: 3