I have developed two classes Ptr and Cntr as part of the Accelerated C++ Ch.14-6 exercise.
- The Ptr class is a handle class that contains a pointer member and allows the user to control whether or not to copy the underlying object referenced by the pointer.
- The Cntr class is a class containing a member of
size_t
type which is the count of pointers pointing to a given object.
I receive an error when Ptr attempts to call some (not all) Cntr constructors and the Cntr destructor:
error: no match for call to '(Cntr) (std::size_t*)'
error: no match for call to '(Cntr) ()'
I have solved some issues by moving constructors into initialization lists in Ptr. However, in other cases I need to call the ~Cntr() destructor outside an initialization list. Guidance as to why this works it works in an initialization list but not outside would help also.
This code sample is not small but within limits of other code I've seen on stackoverflow.com. My complete ptr.h header file is listed as follows:
#ifndef GUARD_Ptr
#define GUARD_Ptr
//Ptr.h header file
#include "vec.h"
using std::size_t;
template <class T> T* clone (const T* tp);
template<> Vec<char>* clone(const Vec<char>* vp);
template <class T> class Ptr;
class Cntr {
public:
size_t* refptr; // member made public while debugging
Cntr() : refptr(new size_t(1)) { }
Cntr(const Cntr& cntptr) : refptr(cntptr.refptr) { ++*refptr; }
Cntr(size_t* t) : refptr(t) { }
~Cntr()
{
delete refptr;
}
size_t value() {
return *refptr;
}
size_t add() {
++*refptr;
return *refptr;
}
size_t subtract() {
--*refptr;
return *refptr;
}
};
template <class T>
class Ptr {
public:
// new member to copy the object conditionally when needed
void make_unique()
{
if (cntptr.value() != 1) {
cntptr.subtract();
cntptr(new size_t(1));
p = p? clone(p) : 0; // call the global version of close
}
}
// the rest of the class looks like Ref_handle except for its name
Ptr() : p(0), cntptr() { }
Ptr(T* t): p(t), cntptr() { }
Ptr(const Ptr<T>& h): p(h.p), cntptr(h.cntptr) { }
Ptr<T>& operator=(const Ptr<T>& rhs)
{
cntptr.add();
// free the lhs, destroying pointers if appropriate
if (cntptr.subtract() == 0) {
~cntptr();
delete p;
}
// copy in values from the rhs
cntptr(rhs.cntptr);
p = rhs.p;
return *this;
}
~Ptr()
{
if (cntptr.subtract() == 0) {
~cntptr();
delete p;
}
}
operator bool() const { return p; }
T& operator*() const {
if (p)
return *p;
throw std::runtime_error("unbound Ptr");
}
T* operator->() const {
if (p)
return p;
throw std::runtime_error("unbound Ptr");
}
private:
T* p;
Cntr cntptr;
};
#endif //GUARD_Ptr