2011-09-22 5 views
1

아이디어는 내가 포인터가 아니었던 것처럼 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에서 클래스를 상속 만들 필요가 없습니다 방법은 무엇입니까?

내가 이런 식으로한다면, 내가 알아서해야주의해야 할 점은 무엇입니까?

+2

왜 포인터를 역 참조할만한 이유가 있습니까? '* ptrA = * ptrB;'? – RobH

+0

이라는 아이디어는 실제로는 포인터라는 사실을 숨기는 것이기 때문에 – uray

+1

실제로 포인터라는 사실은 일반적으로 공유 가능한 데이터에 대한 기능입니다. 그렇지 않으면, 다른 객체가 같은 것에 별명을 붙일 수 있다는 것이 명백하지 않으므로'a = b'가'c'의 값을 변경할 수 있습니다. 의심의 여지가 당신이 그것을 포인터로 숨기고 싶은 경우가 있습니다. 가장 명백한 것은 실제로 공유되지 않는다는 것입니다 (shared_ptr을 사용 했음에도 불구하고), 그것은 pImpl입니다. –

답변

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 
    } 
} 
+0

좋은 대안, thx .. :) – uray

1

operator=은 오버로드중인 클래스의 멤버 여야합니다. 그래서 아닙니다, 당신은 정말로 방해받지 않고 그렇게 할 수 없습니다.

1

아니요,이 작업을 투명하게 수행 할 수 없으며 가능한 경우 매우 혼란스러워 할 수 있습니다.

-1

역 참조 공유 포인터 :

std::shared_ptr<float> obj(new float); 
*obj = 3.14; 
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로 수집 한 가비지. 이것은 또한 의식적인 선택입니다. 참고 카운팅은 쓰레기 수거에 대한 아주 나쁜 대안입니다.

관련 문제