Constant const confusion


#1

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?


#2

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.


#3

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.


#4

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!!!


#5

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”.