I have a mixin class that makes a class reference counted that looks like this:
template<class D>
class ref_count_base
{
protected:
ref_count_base();
ref_count_base(ref_count_base const& x);
ref_count_base(ref_count_base&& x);
ref_count_base& operator=(ref_count_base const& x) &;
ref_count_base& operator=(ref_count_base&& x) &;
~ref_count_base();
private:
int* refs_;
};
// omitted constructors...
template<class D>
ref_count_base<D>::~ref_count_base()
{
if (!refs_)
return;
if (1 == *refs_) {
// C-style cast rather than static_cast allows us to call a member
// function in the derived class even if we are a private base.
((D*)this)->last_ref_released();
delete refs_;
} else {
--*refs_;
}
}
This class is then used like this:
class program : private ref_count_base<program>
{
private:
void last_ref_released()
{
glDeleteProgram(name_);
}
private:
GLuint name_;
friend ref_count_base;
};
Obviously this doesn't work, because program
is no longer alive when we reach the mixin's destructor and so we can't call last_ref_released
in the derived class, but is there a similar way to accomplish this (preferrably without adding noise to the derived class)?
Edit: here is an example of client code:
class entity
{
private:
// some other data members...
program prog_;
};
std::vector<entity> entities_;
for (auto& i : entities_) {
//i.bind_program();
glUseProgram(i.get_program_name());
// drawing code here...
}
Note that with a shared_ptr<program>
instead of a program
this will look
like glUseProgram(i->get_program_name())
.
Edit: the confusion was that you're not trying to reference count the
program
class, but to reference count copies ofname_
with the same value.Given this, it seems cleaner to create something with similar semantics to
shared_ptr
, but for value types ... let's call itshared_value
:and use it like:
You can add flexibility with a polymorphic deleter here - I've just shown the simplest thing that should work for you.
There's an easy way to do what you want, without using CRTP or mixins or touching the program class at all. Simply write it like this:
and then use
std::shared_ptr<program>
everywhere you currently useprogram
(that is, only create one instance and then pass around shared pointers to it).If you don't have
std::shared_ptr
yet, useboost::shared_ptr
instead.