访问由std :: shared_ptr包装的类的运算符重载

时间:2011-09-22 09:15:19

标签: c++ inheritance stl overloading shared-ptr

我的想法是,我想要一个由std::shared_ptr包裹的类,仍然可以使用 就像它们不是指针一样,例如我的类中定义的operator = 我的课程被std::shared_ptr包裹后仍然可以使用。

例如

template <class Ty> class shared_ptr_proxy : public std::shared_ptr<Ty> {
public:
    template<class Other> shared_ptr_proxy& operator=(const Other& rhs)
    {
        (*this->get()) = rhs;
        return *this;
    }
    template<class Other> explicit shared_ptr_proxy(Other * ptr) 
        : std::shared_ptr<Ty>(ptr){};
};

// usage :
shared_ptr_proxy<float> obj = shared_ptr_proxy<float>(new float);
obj = 3.14;

它的工作,但是有一种方法我不需要创建shared_ptr_proxy或 从std::shared_ptr继承一个类?

如果我喜欢这个,有什么警告我应该照顾吗?

5 个答案:

答案 0 :(得分:3)

这取决于您想要代理的内容。完整代理可能会使其看起来与您拥有的价值完全相同,因此您需要提供转换运算符。

在这种情况下,从shared_ptr继承可能不是一个好主意,因为您可能会继承您希望依赖隐式转换的函数。

比较排序对项目的排序方式:

#include <memory>
#include <vector>
#include <algorithm>
#include <iostream>

template <class Ty> class shared_ptr_proxy   {
    std::shared_ptr<Ty> ptr;
public:
    template<class Other> explicit shared_ptr_proxy(Other * p) 
        : ptr(std::shared_ptr<Ty>(p)){};

    template<class Other> shared_ptr_proxy& operator=(const Other& other)
    {
        *ptr = other;
        return *this;
    }

    operator Ty& () { return *ptr; }
    operator const Ty& () const { return *ptr; }
};

int main()
{
    std::vector<shared_ptr_proxy<int> > vec {
        shared_ptr_proxy<int>(new int(10)), 
        shared_ptr_proxy<int>(new int(11)), 
        shared_ptr_proxy<int>(new int(9))
    };
    vec.back() = 8;  //use assignment
    std::sort(vec.begin(), vec.end());  //sort based on integer (not pointer) comparison
    for (unsigned i = 0; i != vec.size(); ++i) {
        std::cout << vec[i] << ' ';  //output stored values
    }
}

#include <memory>
#include <vector>
#include <algorithm>
#include <iostream>

template <class Ty> class shared_ptr_proxy : public std::shared_ptr<Ty>   {
public:
    template<class Other> explicit shared_ptr_proxy(Other * p) 
        : std::shared_ptr<Ty>(p){};

    template<class Other> shared_ptr_proxy& operator=(const Other& other)
    {
        *this->get()= other;
        return *this;
    }

    operator Ty& () { return *this->get(); }
    operator const Ty& () const { return *this->get(); }
};

int main()
{
    std::vector<shared_ptr_proxy<int> > vec {
        shared_ptr_proxy<int>(new int(10)), 
        shared_ptr_proxy<int>(new int(11)), 
        shared_ptr_proxy<int>(new int(9))
    };
    vec.back() = 8;  //the only thing that works
    std::sort(vec.begin(), vec.end());  //sort based on pointer values
    for (unsigned i = 0; i != vec.size(); ++i) {
        std::cout << vec[i] << ' ';  //outputs addresses
    }
}

答案 1 :(得分:1)

operator=必须是您正在重载的类的成员。所以不,你不能真正做到这一点非侵入性。

答案 2 :(得分:1)

不,你不能透明地做到这一点,如果可以,那可能会让人感到困惑。

答案 3 :(得分:0)

抱歉,我不认为你可以在没有继承或自定义包装的情况下逃脱,你不能在operator =的定义之外重载shared_ptr,并且在这种情况下不推荐继承shared_ptr的性质。但是,如果你编写一个自定义包装器,你可以使它足够通用,它适用于所有类型。

只有在C ++ 11中才有可能,即使在那里也很难。您需要decltypestd::declval来推断运算符的返回类型,并使用rvalue引用和std::forward来完美地转发参数。有关示例,请参阅this question及其答案。

正如那个问题所提到的,我实现了一个指针包装类:http://frigocoder.dyndns.org/svn/Frigo/Lang/ref

然而,与您想要的相比,它有一些差异:

  • operator = (ref&)operator = (ref&&)都只复制指针。但是,由于这个和代理的复制构造函数,隐式operator = (const T&)执行复制构造和指针复制而不是赋值或获取地址。这是我的一个有意识的选择,如果共享对象,赋值可能会产生问题,并且从堆栈分配的对象中获取指针是不安全的。

  • 由于GCC未实现的功能,使用operator +=等复合赋值运算符的返回类型不起作用。这是没有问题的,因为它们被重新解释:x += y调用x = (x + y),执行复制/移动构造和指针复制。这也是我的一个有意识的选择,以保持共享对象不变。

  • 用Boehm GC收集的垃圾而不是参考计数。这也是我的一种有意识的选择,引用计数是垃圾收集的一个非常糟糕的选择。

答案 4 :(得分:-1)

取消引用共享指针:

std::shared_ptr<float> obj(new float);
*obj = 3.14;