Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can smart pointers selectively hide or re-direct function calls to the objects they are wrapping?

I'm working on a project where certain objects are referenced counted -- it's a very similar setup to COM. Anyway, our project does have smart pointers that alleviate the need to explicitly call Add() and Release() for these objects. The problem is that sometimes, developers are still calling Release() with the smart pointer.

What I'm looking for is a way to have calling Release() from the smart pointer create a compile-time or run-time error. Compile-time doesn't seem possible to me. I thought I had a run-time solution (see code below), but it doesn't quite compile either. Apparently, implicit conversion isn't allowed after using operator->().

Anyway, can anyone think of a way to accomplish what I'm trying to accomplish?

Many thanks for your help!

Kevin

#include <iostream>
#include <cassert>

using namespace std;

class A
{
public:
    void Add()
    {
        cout << "A::Add" << endl;
    }

    void Release()
    {
        cout << "A::Release" << endl;
    }

    void Foo()
    {
        cout << "A::Foo" << endl;
    }
};

template <class T>
class MySmartPtrHelper
{
    T* m_t;

public:

    MySmartPtrHelper(T* _t)
        : m_t(_t)
    {
        m_t->Add(); 
    }

    ~MySmartPtrHelper()
    {
        m_t->Release(); 
    }

    operator T&()
    {
        return *m_t;
    }

    void Add()
    {
        cout << "MySmartPtrHelper::Add()" << endl;
        assert(false);
    }

    void Release()
    {
        cout << "MySmartPtrHelper::Release()" << endl;
        assert(false);
    }
};

template <class T>
class MySmartPtr
{
    MySmartPtrHelper<T> m_helper;

public:

    MySmartPtr(T* _pT)
        : m_helper(_pT)
    {
    }

    MySmartPtrHelper<T>* operator->()
    {
        return &m_helper;
    }
};

int main()
{
    A a;

    MySmartPtr<A> pA(&a);

    pA->Foo(); // this currently fails to compile.  The compiler
               // complains that MySmartPtrHelper::Foo() doesn't exist.

    //pA->Release(); // this will correctly assert if uncommented.

    return 0;
}
like image 565
Kevin Avatar asked Jun 05 '09 07:06

Kevin


1 Answers

You can't do it - once you've overloaded the operator -> you're stuck - the overloaded operator will behave the same way reardless of what is rightwards of it.

You could declare the Add() and Release() methods private and make the smart pointer a friend of the reference-counting class.

like image 115
sharptooth Avatar answered Dec 11 '22 20:12

sharptooth