Hans Dembinski wrote:
Out of curiosity, what's the specific problem that was pointed out? What behavior is undefined?
I was pointed to this answer on SO: https://stackoverflow.com/questions/34737737/relation-between-numeric-repres...
I am relying on two things: - memory addresses map trivially to consecutive integers - the address of aligned memory allocated by Boost.Align always converts into an integer that is a multiple of the alignment value
Neither seems to be guaranteed by the standard. The conversion from memory address to integer is an implementation detail, the SO answer gives examples of "exotic" mappings which are conceivable (not that there is any machine out there which actually does it this way).
As far as I can see, you're storing an uintptr_t. This is not undefined. The only thing you're missing is an ASSERT that the tag_mask part is 0 after the reinterpret_cast. Yes, this is not guaranteed to work in principle, but if it does, it's not undefined. Your converting constructor seems broken though. Even if we put aside the problem that destroying U* is not the same as destroying T*, you have to convert to T* first, then to U*, then back to uintptr_t. (And assert here as well, as the new value is no longer guaranteed to have a tag_mask of 0.) Stepping back a bit, I would have expected a tagged_ptr to be a low-level component that just adds tag bits to a pointer, rather than being responsible for allocating and destroying objects and arrays. Perhaps the way you've implemented it makes it more useful for certain scenarios though, I'm not sure.