If I have a boost::shared_array<T> (or a boost::shared_ptr<T[]>), is there a way to obtain a boost::shared_ptr<T> which shares with the array?
So for example, I might want to write:
shared_array<int> array(new int[10]);
shared_ptr<int> element = &array[2];
I know that I can't use &array[2], because it just has type int *, and it would be dangerous for shared_ptr<int> to have an implicit constructor that will take that type. Ideally shared_array<int> would have an instance method on it, something like:
shared_ptr<int> element = array.shared_ptr_to(2);
Unfortunately I can't find anything like this. There is an aliasing constructor on shared_ptr<int> which will alias with another shared_ptr<T>, but it won't allow aliasing with shared_array<T>; so I can't write this either (it won't compile):
shared_ptr<int> element(array, &array[2]);
//Can't convert 'array' from shared_array<int> to shared_ptr<int>
Another option I played with was to use std::shared_ptr<T> (std instead of boost). The specialisation for T[] isn't standardised, so I thought about defining that myself. Unfortunately, I don't think that's actually possible in a way that doesn't break the internals of the aliasing constructor, as it tries to cast my std::shared_ptr<T[]> to its own implementation-specific supertype, which is no longer possible. (Mine is currently just inheriting from the boost one at the moment.) The nice thing about this idea would have been that I could implement my instance shared_ptr_to method.
Here's another idea I experimented with, but I don't think it's efficient enough to be acceptable as something we're potentially going to use throughout a large project.
template<typename T>
boost::shared_ptr<T> GetElementPtr(const boost::shared_array<T> &array, size_t index) {
    //This deleter works by holding on to the underlying array until the deleter itself is deleted.
    struct {
        boost::shared_array<T> array;
        void operator()(T *) {} //No action required here.
    } deleter = { array };
    return shared_ptr<T>(&array[index], deleter);
}
The next thing I'm going to try is upgrading to Boost 1.53.0 (we currently only have 1.50.0), using shared_ptr<T[]> instead of shared_array<T>, and also always using boost instead of std (even for non-arrays). I'm hoping this will then work, but I haven't had a chance to try it yet:
shared_ptr<int[]> array(new int[10]);
shared_ptr<int> element(array, &array[2]);
Of course I'd still prefer the instance method syntax, but I guess I'm out of luck with that one (short of modifying Boost):
shared_ptr<int> element = array.shared_ptr_to(2);
Anyone else have any ideas?
You are doing strange stuff.
Why do you need shared_ptr to element? Do you want element of array be passed somewhere else and hold down your array from removal?
If yes, than std::vector<shared_ptr<T>> is more suited for that. That solution is safe, standard and has fine granularity on objects removal
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With