On 1/28/2016 5:07 PM, Nat Goodspeed wrote:
Do you mean, for example, that you can create a registered_ptr to an instance within the constructor? (I haven't looked at your implementation.)
So first, let me say that I am by no means a C++ (or boost or stl) expert. If I understand your question, the short answer is yes, sort of. But there's a longer answer. You are asking if a registered_ptr can replace the raw pointer in this scenario?: class CA { public: CA() { m_ptr_to_this = this; } CA* m_ptr_to_this; }; CA a_obj; I actually have two implementations - one called TRegisteredPointer and one called TRegisteredPointerForLegacy. TRegisteredPointerForLegacy is a little slower, but more "lenient" / less "strict" / more compatible with raw pointers. With TRegisteredPointerForLegacy, this is no problem: class CA { public: CA() { m_ptr_to_this = this; } mse::TRegisteredPointerForLegacy<CA> m_ptr_to_this; }; mse::TRegisteredObjForLegacy<CA> a_obj; My implementation of TRegisteredPointer is more strict than TRegisteredPointerForLegacy and doesn't (currently) support this. The two implementations represent different tradeoffs between speed & safety and compatibility & flexibility.
my implementation can only target types that can act as base classes. By default most classes can act as a base class, but native types like int, bool, etc. cannot.
That could be a bigger problem than it appears, given 'final' classes.
Umm, yes maybe. Personally, I never use 'final' classes, so my implementation currently uses the target object as a base class. But it could be (and probably will be) extended to also support the target object as the derived class instead. This is the way "QPointer" works if you're familiar with Qt. Basically we need a certain function to be called when the target object is destructed and we don't really care how it's done. We can add a destructor by deriving a new class from the target class, or we can add a destructor by having the target class be derived from a specific class, or frankly, the appropriate code can be manually inserted into the existing destructor of the target class. Either way will work. Using the target class as a base class is just the "cleanest", least "intrusive" of the options. It's true, it doesn't seem that this kind of pointer can be implemented in a way that's as "universal" as, say std::shared_ptr. And maybe that's why boost doesn't already include something like it. But is that sufficient reason to forego the real functional benefits of this kind of pointer?
Um... I'm not sure people would regard use of those substitutes as an acceptable requirement for working with registered_ptr.
Yeah, another shortcoming I would've liked to have avoided if there was some way to do so. But to be clear, you only need to use the substitutes if you're pointing directly at a primitive type. Pointing to a class that contains primitive types is not an issue. How often do people declare a pointer to a single int? I don't think I can remember the last time I did. But maybe that's just me. But anyway, I'm kind of taking a stand on this particular issue, and I invite boost, and the wider C++ community to join me. int, unsigned int, and the other primitives are a legacy inherited from C. A bad (and unnecessarily dangerous) legacy that needs to be tossed, in my opinion. To be clear, registered_ptr doesn't require using *my* substitutes when pointing to primitive types. Presumably any substitute that can act as a base class would work just as well. The substitutes I provide are such a thin wrapper that I assume any respectable compiler should generate the exact same machine code (in release mode) when used as a direct substitute for their native counterparts. But my substitutes are safer in that they have default initialization. And they also address the bug prone implicit conversion between signed and unsigned ints. I'm not against using native primitives in all cases but, in my opinion, they shouldn't still be the default.
Of course the ideal would be smart pointers that could distinguish between stack allocated objects and heap allocated objects. Unfortunately, as far as I know, (standard) C++ doesn't seem to give us that facility.
Heh. I've wished for some time for the ability to constrain a class: "this cannot be static" or "this cannot be instantiated on the stack" or "this cannot be instantiated on the heap." But I've never been sufficiently motivated to write a proposal -- or, come to that, search through WG21 archives for an existing proposal.
A good language facility that addressed my use case should also address yours, of course.
I haven't had time to investigate it, but I came across this project: https://github.com/crdelozier/ironclad/. It seems to be abandoned, but from what I could tell, it used platform specific code to determine if a pointer was pointing to the stack or not.