While working on an RAII-style guard object, I ended up encoding some of the guard state in a template parameter. This seems reasonable if, for instance, you want a recursive / nested guard object that's aware of how many levels deep it is but without space overhead (being pedantic, I know) or to eliminate some runtime overheads. This turned into an academic curiosity though...
Something like this would be an example:
template <unsigned depth>
class guard {
unsigned get_depth() const {return depth;}
};
guard<2> g2;
std::cout << reinterpret_cast< guard<5>* >( &g2 )->get_depth(); // works? crazy? useful?
I cannot for the life of me think of a legitimate reason to do this, but it got me thinking if this is legal C++ and just how the compiler ought to handle something like this (if it can at all) or if it's just silly through and through.
I assume because the cast target needs to be known at compile time, that the relevant template is instantiated for the cast. Has anyone found something like this useful, assuming it does work and has uses at all, and if so where could this be utilized?
The general question I guess is can reinterpret_cast
alter constant template parameters? If so is this just a type hack (for want of a better term) and g2
in this case would always return 2
(after casting)? Or should it return 5
(after casting)?
This is undefined but not because of the strict aliasing rule. The call to get_depth
neither reads nor modifies the value of any object (a template non-type parameter isn't an object), so it doesn't access (as defined in [defns.access]) anything within the meaning of the strict aliasing rule.
This is controlled instead by [class.mfct.non-static]/2:
If a non-static member function of a class
X
is called for an object that is not of typeX
, or of a type derived fromX
, the behavior is undefined.