A new generic pointer any_ptr (now dumb_ptr) to make code more reusable among smart pointers

佐手、 提交于 2019-12-05 19:55:54

With such a class any_ptr, you will not be able to do practically anything other than * and ->. No assignment, copy construction, duplication or destruction. if that's all you need then just write the function taking as argument the raw pointer T* and then call it use .get() or whatnot on your automatic pointer.

You can use different smart pointers because they offer different semantics and tradeoffs.

What would be the semantics of any_ptr ? If it comes from unique_ptr / scoped_ptr it should not be copied. If it comes from shared_ptr or weak_ptr it would need their heavy machinery for reference counting.

You would have a type with all the disadvantages (heavy, no copyable) for little gain...


What you have here is a problem of interface. Unless the methods manage the lifetime of the object (in which case the exact pointer type is required), then it need not be aware of how this lifetime is managed.

This means that methods that merely act on the object should take either a pointer or a reference (depending on whether it might be null), and be called accordingly:

  • void foo(T* ptr); which is called shared_ptr<T> p; foo(p.get());
  • void foo(T& ptr); which is called foo(*p);

Note: the second interface is much more pointer agnostic

This is plain encapsulation: a method need be aware only of the bare minimum it needs to operate. If it does not manage the lifetime, then exposing how this lifetime is managed to the method... causes those ripples that you've witnessed.

If your methods really have to be smart pointer-agnostic, why not pass a garden variety pointer:

virtual void MyMethod(MyClass* ptr)
{
    ptr->doSomething();
}

and do

MyObj->MyMethod(mySmartPtr.get());

at the call site ?

You can even pass a reference:

virtual void MyMethod(const MyClass& ptr)
{
    ptr->doSomething();
}

and do

MyObj->MyMethod(*mySmartPointer);

which has the advantage to have pretty much always the same syntax (except for std::weak_ptr).

Otherwise, smart pointer types are becoming standard: std::unique_ptr, std::shared_ptr and std::weak_ptr have their use.

Smart pointers are for storing objects according to certain resource management semantics. You can pretty much always extract a bare pointer from them.

Methods should therefore in general expect bare pointers, or specific kinds of smart pointers in case they need to. For instance, you can pass a shared_ptr by const reference in order to store a shared handle to an object.

To this goal, you can add typedefs:

struct MyClass
{
    typedef std::shared_ptr<MyClass> Handle;
    static Handle CreateHandle(...);

    ...

private:
    Handle internalHandle;
    void setHandle(const MyClass::Handle& h);
};

and do

void MyClass::setHandle(const MyClass::Handle& h)
{
    this->internalHandle = h;
}

When this happens and you change your pointer type you have to either go and change a whole bunch of you method signatures to take the new pointer type, or at each call site you have to convert between pointer types. You also have a problem if you have the same function but want it to take multiple pointer types.

I am wondering if there already exists a generic way to deal with, i.e. write methods that are agnostic of the pointer type you pass to it?

You almost answered your own question.

A smart-pointer should be present in function signatures only if ownership of an object is being transferred. If a function does not take ownership of an object, it should accept it by plain pointer or reference. Only functions that need to own an object or extend its lifetime should accept it by smart pointer.

Answering my own question so it doesn't appear in the unanswered list. Basically none of the other answers found what I considered to be a serious flaw in my idea. Props to @Alexandre C. for understanding what I was trying to do.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!