ReferenceCountedObjectPtr and inheritance


#1

Hello !

I’m changing some code to make it use ReferenceCountedObject and ReferenceCountedObjectPtr and I noticed that :
If an object B inherits from A, ReferenceCountedObjectPtr cannot be converted automatically to ReferenceCountedObjectPtr !

I had something like :

[code]class A
{
}

class B : public A
{
}

SomeObject::SomeMethod(A* param);

[/code]

I could pass “SomeMethod” a pointer to a B, it was fine.

Now that I have

[code]class A: ReferenceCountedObject
{
}

class B : public A
{
}

SomeObject::SomeMethod(A::Ptr param)

[/code]

X::Ptr being defined ReferenceCountedObjectPtr , I can’t pass a B::Ptr to my method.
I understand it makes sense because we are passing a stack object instead of a pointer here. However I’m looking for a workaround.

Any thoughts or solutions ?


#2

Pass it as a regular pointer. If it came from a reference counted object pointer, it is guaranteed to exist for at least the duration of the function call.

If you must store it, still pass it as a B* but remember it as a RefCountedObjectPtr.


#3

Yep seems like the only solution, however Jules always warns about mixing regular pointers and RefCountedObjectPtr so I guess there must be a good reason for this ? :slight_smile:

P.S. : I mean, a deeper reason than the user inadvertently deleting the regular pointer


#4

Avoid mixing them. Unless you have to. In your case, you do.


#5

I think I’ll end up using boost::shared_ptr instead because they implement
this feature unless of course Jules plans to implement the same thing in Juce, which would be neat (I don’t know why but I always choose Juce instead of Boost when the same functionality is available in both :wink: )


#6

The boost stuff needs a dynamic_shared_cast because it’s a non-intrusive pointer, so it’s not safe to cast a shared_ptr to a normal pointer and then back to a shared_ptr again. With ReferenceCountedObjectPtr, it is safe to do that, as long as you know that the object isn’t going to be deleted while you’re still using a raw pointer to it.

The reason I didn’t add a similar function/method to dynamically cast them is because VC6 didn’t support the syntax required (I think it couldn’t handle an explicit template type when calling a function). Now that people are finally starting to give up on VC6 it might be possible to add such a feature.


#7

While ReferenceCounterObjectPtr is on topic, might I suggest a small addition ? I’m trying to setup a serialization through boost, and I have a lot of ReferenceCounterObjectPtr in STL containers. I’d like to be able to get to the type which ReferenceCounterObjectPtr is wrapping. So I’d like this :

template <class ReferenceCountedObjectClass>
class ReferenceCountedObjectPtr
{
public:
    typedef ReferenceCountedObjectClass referenced_type;

    //==============================================================================
    /** Creates a pointer to a null object. */
    inline ReferenceCountedObjectPtr() noexcept
        : referencedObject (nullptr)
    {
    }
...

For an STL container

typedef std::vector<ReferenceCountedObjectPtr<MyClass> > vector_type;

the ultimate type is then vector_type::value_type::referenced_type

/R


#8

Sure, I can add a typedef, though I’d call it ReferencedType (you didn’t use “referenced_type” because it’s some kind of standard STL type name, did you?)


#9

ReferencedType will be just fine, thanx! :slight_smile:


#10

Can we please be consistent with names? Using the Juce style, it would be “ReferencedTypeForTheReferenceCountedObjectPtr”


#11

:lol:

or… maybe “ThisIsATypeDefForTheClassTypeThatTheReferenceCountedObjectPtrIsReferencingType”… ?


#12

Yes, it’s no big deal, it’s just a matter of code cleanness :smiley:

Sweet banana of jamaica, there are still people using the-compiler-who-shouldn’t-be-named ? Freaky !
After working 3 years with it, I think VC6 couldn’t handle C++. Period. :twisted:

That would be nice to have this dynamic_cast (not a must havce but a nice to have) allong with a #ifdef for VC6 users, in juce.


#13

Actually now that I come to think lf it, I have need of exactly what the original poster is describing. This is my class hierarchy:

struct IFolder : ReferenceCountedObject
{
  typedef ReferenceCountedObject <IFolder> Ptr;
  //...
};

struct Folder : IFolder
{
  typedef ReferenceCountedObject <Folder> Ptr;
  //...
};

struct Dir : Folder 
{
   typedef ReferenceCountedObject <Folder> Ptr;
  //...
};

struct DirImpl : Dir
{
  // ...
};

This no worky:

IFolder::Ptr getIFolder (Dir::Ptr dir)
{
  return dir;
}

#14

[quote]IFolder::Ptr getIFolder (Dir::Ptr dir) { return dir; }[/quote]

Isn’t this :

IFolder::Ptr getIFolder (Dir::Ptr dir) { return IFolder::Ptr(dir.getObject()); }

working ?


#15

Well yeah but there are many places where a ReferenceCountedObjectPtr to a class higher up in the inheritance chain is needed, but what is available is the more-derived ReferenceCountedObjectPtr, not always in return values (i.e. used in expressions).