On 1/29/2016 7:00 PM, Rob Stewart wrote:
Have a look at boost::intrusive_ptr.
If I understand boost::intrusive_ptr correctly, and I'm not totally sure that I do, I think it kind of further makes the case for including registered_ptrs. This post http://baptiste-wicht.com/posts/2011/11/boost-intrusive_ptr.html implies the point of boost::intrusive_ptr is increased performance. But it appears that, like shared_ptr, it's meant to be used for heap allocations. But of course, often the biggest performance improvement by far would come from avoiding any heap allocation whatsoever. Which is what (at least one implementation of) registered_ptr can do no problem. Some simple benchmarks here http://duneroadrunner.github.io/SaferCPlusPlus/#simple-benchmarks show that registered_ptrs targeting the stack far outperform even native pointers targeting the heap (when you include the allocation and deallocations). I'm thinking that maybe registered_ptr could be re-branded the "high performance" smart pointer. In which case, one could pose the question as "does it's warts (it's issues with primitive types and 'final' classes) justify excluding the 'high performance' smart pointer"?
Many times I don't want to initialize a variable because the branches in the subsequent code select the value. Do your wrappers provide a constructor that permits leaving the value uninitialized?
So first let me say that I'm not proposing a total ban on primitive types. When you need the performance, and primitive types give you the performance, use them. But that should be small fraction of the world's total C++ code. What is antiquated, in my opinion, is that primitive types are the still the default. In terms of not wanting to initialize due to subsequent conditional assignment, I would say don't underestimate the compiler optimizer. When the optimizer can figure out that the default initialization is redundant, it will remove it for you, right? I should note though, that I found it difficult (or impossible) to fully mimic all the implicit conversion rules of primitive types, so there are going to be some cases where the substitute classes can't be used (without rewriting some of your code) for compatibility reasons.
And they also address the bug prone implicit conversion between signed and unsigned ints.
Once you do that, shouldn't you go the rest of the way and check all conversions? For example, what about overflow during marketing narrowing?
I don't know what "marketing narrowing" is, but recently on this newsgroup people have been discussing a "safe integer" or "safe numerics" library that seems to have taken it all the way, and maybe even a bit further. My types do check ranges when converting to different integer/char types. It's been a while, but if anyone's interested they're implemented here https://github.com/duneroadrunner/SaferCPlusPlus/blob/master/mseprimitives.h and examples of their functionality in action are here https://github.com/duneroadrunner/SaferCPlusPlus/blob/master/msetl_example.c... (search for "mse::CInt"). I am not trying to push my specific primitive substitutes. I'm sure people will (or have) come up with better ones. I chose certain safety-performance-compatibilty-time-effort tradeoffs when implementing my primitive substitutes, but I would certainly defer to anyone else who wants to address the issue. I would say two things though: One - It might be helpful if boost, or whoever, adopted a standard set of primitive substitutes that compilers could recognize and optimize for. And two - By default, an unsigned integer minus another unsigned integer should really return a signed integer, like my primitives do.