I spent a small amount of time at Microsoft working in the legacy Office codebase. It is kind of a parallel universe to normal C++ - lots of ideas in it predate their STL equivalents, and some have yet to make it to the outside world. Some ideas just went off in different directions. Shared pointers are one of the latter. I no longer recall the exact name of the type, but Office shared pointers are intrusive - your interface inherits from `IMsoSharedRef<IMyInterface>` or something like that, and your concrete types would in turn inherit `SharedRef` or whatever.
There are a number of really interesting aspects to this family of types, but the one that's relevant here is that it handles situations like this very gracefully. If you want to pass your shared object to a function that won't take ownership (shared or otherwise), it's simple - the type just decays into a raw pointer. So your function can be
This is of course a double-edged sword because you have to know that your callee won't try to hang on to that pointer. Even so, I never once in all of my (very strict) code reviews heard anything about the proper way to pass pointers. (and believe me, it's the kind of codebase where you _will_ hear about that kind of thing).
It's been a few years so maybe some details are wrong, but the gist of it is correct.
Oh hey, I just discovered that MS open-sourced the lowest levels of the Office codebase, including the stuff I talked about. The most common shared pointer type is actually the inscrutibly-named `TCntPtr`, but the file that covers most of what I talked about above is https://github.com/microsoft/Mso/blob/master/libs/object/inc....
Neat! ...not that I'd ever use it, or recommend its use. Its tradeoffs make perfect sense for Office but probably not for general-purpose applications.
the standard library has enable_shared_from_this, an opt-in base that allows safely constructing a shared pointer from a raw pointer, implicitly enabling intrusive counting. Implicit conversion to raw pointer woudl just extremely unsafe though:
std::shared_ptr<int> x {new int(0)};
{
std::unique_ptr<int> y{x}; // not actually allowed
} // boom
That's true! This is one of those instances of parallel evolution. The MSO construct predates even Boost's `enable_shared_from_this`, as I recall. FWIW when I was there, new code was encouraged to use STL smart pointers where possible - people were always looking for opportunities to shed legacy patterns where we could.
I totally agree about the danger of implicit conversion to raw pointers - it breaks the whole point of smart pointers. The reason it makes sense for Office is that huge swathes of code are written in "c++99" style - no exceptions, all functions return HRESULT error codes, and most functions are very explicit about who owns what. By convention, functions accepting pointers almost (?) never hang on to those pointers. Those functions that _do_ take ownership of (or retain an interest in) a pointer argument, explicitly ask for a smart pointer.
Like I said, not really suitable for general use, but darn convenient _within the context of Office_.
There are a number of really interesting aspects to this family of types, but the one that's relevant here is that it handles situations like this very gracefully. If you want to pass your shared object to a function that won't take ownership (shared or otherwise), it's simple - the type just decays into a raw pointer. So your function can be
and you can call it with your smart pointer This is of course a double-edged sword because you have to know that your callee won't try to hang on to that pointer. Even so, I never once in all of my (very strict) code reviews heard anything about the proper way to pass pointers. (and believe me, it's the kind of codebase where you _will_ hear about that kind of thing).It's been a few years so maybe some details are wrong, but the gist of it is correct.