访问由std::shared_ptr封装的类的操作符重载
accessing operator overloading of class which is wrapped by std::shared_ptr
的想法是,我想要一个由std::shared_ptr
包装的类,仍然可以使用就像它们不是指针一样,例如在我的类中定义的操作符=仍然可以使用后,我的类是由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
继承类?
和
如果我这样做,是否有我应该注意的警告?
这取决于您想要代理做什么。一个完整的代理可能使它看起来完全像您拥有该值,因此您将提供转换操作符。
在这种情况下,从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
}
}
operator=
必须是要重载的类的成员。不,你不能做非侵入性的
不,你不能透明地这样做,如果你可以的话,可能会很混乱。
对不起,我不认为没有继承或自定义包装器就可以摆脱,您不能在shared_ptr
的定义之外重载operator =
,并且由于shared_ptr
的性质,在这种情况下不建议继承。然而,如果你编写一个自定义包装器,你可以使它足够通用,它适用于所有类型。
这只能在c++ 11中实现,即使在c++ 11中也很难实现。您需要decltype
和std::declval
来推断操作符的返回类型,需要右值引用和std::forward
来完美地转发参数。请看这个问题和答案的例子。
正如在那个问题中提到的,我实现了一个指针包装器类:http://frigocoder.dyndns.org/svn/Frigo/Lang/ref
然而,它与你想要的有一些差异:
-
operator = (ref&)
和operator = (ref&&)
都只复制指针。然而,由于这一点和代理复制构造函数,隐式operator = (const T&)
进行复制构造和指针复制,而不是赋值或接受地址。这是我有意识的选择,如果对象是共享的,赋值会产生问题,并且从堆栈分配的对象中获取指针是不安全的。 -
接受复合赋值操作符(如
operator +=
)的返回类型不能工作,这是由于GCC未实现的特性。这是没有问题的,因为它们被重新解释:x += y
调用x = (x + y)
,做复制/移动构造和指针复制。这也是我有意识的选择,保持共享对象不变。 -
使用Boehm GC收集垃圾,而不是引用计数。这也是我有意识的选择,引用计数是垃圾收集的一个非常糟糕的选择。
解引用共享指针:
std::shared_ptr<float> obj(new float);
*obj = 3.14;