OOP Class Notes for 12/03/13
C++ Iterators
Generalized Smart Pointers
- In our smart pointer implementation we want to be flexible and have a reference counter that is not invasive. However, the call to our simulated virtual destructor is specific to our translator; the Ptr template is not general enough.
- So we make templates for this, using three separate ways to destroy objects using generic parameters.
template<typename T>
struct object_policy{
static void destroy(T* addr) {
delete addr; //deletes regular C++ class
}
};
template<typename T>
struct array_policy{
static void destroy(T* addr) {
delete[] addr; //deletes regular C++ array
}
};
template<typename T>
struct java_policy{
static void destroy(T* addr){
if(0 != addr) addr -> __vptr->__delete(addr);
}
};
Such templates classes are called traits. The purpose of a trait is to carry information used by another object or algorithm to determine "policy" or "implementation details".
By using traits instead of inheritance we can avoid the run-time overhead of dynamic method dispatch for choosing the right implementation policy.
We integrate the destroy traits into our smart pointer class as follows:
template<typename T, template<typename> class P>
class Ptr{
.
.
.
public:
typedef T value_type;
typedef P<T> policy_type;
.
.
.
policy_type::destroy(addr);
See for the complete code
Policies in action
__rt::Ptr<int, __rt::object_policy> p = new int(5);
__rt::Ptr<double, __rt::array_policy> q = new double[5];
To avoid always writing out the second template argument, we can replace:
template<typename T, template <typename> class P>
with
template<typename T, template <typename> class P = object_policy>
What we learned
C++ Iterators
- The different kind
- Their corresponding tags
- We can make versions of functions for different iterators and the correct one will automatically be selected.
Abstracting destroy line
- Uses policy to pass a template that runs destroy based specifically on what needs to be destroyed.