Constant const confusion

Does this make sense:

typedef ReferenceCountedObjectPtr <MyObject const> MyConstObjectPtr;

This should declare a reference counted pointer to an object which is treated as const (cannot assign to data members and cannot call non-const member functions). The problem of course is that the Atomic in ReferenceCountedObject is not mutable.

Or have I been staring at the screen for too long?

Well, even if the Atomic was mutable, you’d also have the problem that it may have to delete the object when the ref-count hits 0, so even if you bodged it using const_casts and mutables so that a ReferenceCountedObjectPtr to a const object will compile, it’s doesn’t really seem honest somehow, as that const object isn’t really staying const.

A better approach would be to have a ConstReferenceCountedObjectPtr, which takes a non-const object, but only presents accessor methods to get it as a const.

Not sure how std::shared_ptr handles this - they may have found cunning new c++11 tricks to make it all work more transparently.

You can delete through a pointer to a const object (C++ provides for this exceptional case). I have this working in my rip-off of ReferenceCountedObjectPtr, I just made the reference count mutable and changed incReferenceCount() and decReferenceCount() to be const. In my version the counter is a template type (to avoid bringing in a dependency on atomics, which are not universally supported yet).

Click link to see the program output:

codepad.org

struct A {};
int main () {
  A const* a = new A;
  delete a;
  return 0;
}

I’m 100% sure this would work in JUCE.

On a positive note…after hours of banging my head against the wall, getting SFINAE to work with a large assortment of traits templates with all combinations of cv-qualifiers, pointers, references, and objects by value, the const confusion has cleared up!!!

Not such a great idea, because this wouldn’t work:

template <class T>
struct wrapper {
  typedef ReferenceCountedObjectPtr <T> Ptr;
};

struct foo : ReferenceCountedObject {
};

struct bar {
  typedef wrapper <foo const>::Ptr;
}

Yeah I backed myself into a template corner where I had no choice but to support all possible types passed in “T”.