2016-08-14 2 views
2

부울에게 캐스팅에 과부하가 걸리는 내 자신의 ptr로 부작용 ptr을 감싸려고했습니다. 또한, 필자의 ptr에서 일부 부스트 침입 ptrmethod에 대한 액세스를 제한하고 싶습니다. 처음에는 ptr의 private 멤버로 관입 ptr을 강화하고 bool 관용구를 사용했습니다. bool 관용구를 사용하여 잘 작동했습니다. 내 자신의 특별한 이유 때문에 새로운 ptr이 침입 형 ptr 유형이되어야하므로 개인 상속을 사용했지만 작동하지 않았습니다. 어떤 이유로 gcc는 내 ptr을 부작용 ptr로 처리하려고 시도하고 공개적으로 노출 된 bool 관용구를 사용하기를 거부합니다. 여기 는 보여주는 샘플 코드입니다 그것은 :GCC는 개인 상속을 부모로 변환합니다.

부스트 방해 PTR 개인적으로 상속하는 경우
g++ -std=c++11 ./test.cpp 
... 
./test.cpp: In function 'int main()': 
./test.cpp:88:16: error: 'boost::intrusive_ptr<Object>' is an inaccessible base of 'PtrB<Object>' 
    if (obj == NULL) 
       ^
In file included from /usr/include/boost/smart_ptr/intrusive_ptr.hpp:167:0, 
       from /usr/include/boost/intrusive_ptr.hpp:16, 
       from ./test.cpp:1: 
/usr/include/boost/smart_ptr/detail/operator_bool.hpp:60:10: error: 'bool boost::intrusive_ptr<T>::operator!() const [with T = Object]' is inaccessible 
    bool operator!() const BOOST_NOEXCEPT 
     ^
./test.cpp:92:10: error: within this context 
    if (!obj) 
     ^
./test.cpp:92:10: error: 'boost::intrusive_ptr<Object>' is not an accessible base of 'PtrB<Object>' 

, 무엇을 수행하는 GCC 그것을 사용하려고 : 컴파일 오류 코드 결과에 PtrB를 사용

#include <boost/intrusive_ptr.hpp> 
#include <stdio.h> 

class Object 
{ 
    public: 
     Object() : _refCount(0) {} 
     void addRef() { _refCount++; } 
     unsigned int releaseRef() { return --_refCount; } 

    private: 
     unsigned int _refCount; 
}; 

inline void intrusive_ptr_release(Object* p) 
{ 
    if (p->releaseRef() == 0) 
    { 
     delete p; 
    } 
} 

inline void intrusive_ptr_add_ref(Object* p) 
{ 
    p->addRef(); 
} 

// Option A: using private member 
template<class ObjectT> 
class PtrA 
{ 
    public: 
     explicit PtrA(ObjectT* obj) : _obj(obj) {} 
     PtrA() {} 

     ObjectT* operator->() { return _obj.operator->(); } 
     const ObjectT* operator->() const { return _obj.operator->(); } 

     ObjectT* get() { return _obj.get(); } 
     const ObjectT* get() const { return _obj.get(); } 

     typedef const ObjectT* (PtrA::*unspecified_bool_type)() const; 

     operator unspecified_bool_type() const 
     { 
      if (_obj != NULL) 
      { 
       printf("ptr is not null\n"); 
      } 

      return _obj.get() == 0 ? 0: (unspecified_bool_type)&PtrA::get; 
     } 

    private: 
     boost::intrusive_ptr<ObjectT> _obj; 
}; 

// Option B: using private inheritance 
template<class ObjectT> 
class PtrB : private boost::intrusive_ptr<ObjectT> 
{ 
    public: 
     explicit PtrB(ObjectT* obj) : boost::intrusive_ptr<ObjectT>(obj) {} 
     PtrB() {} 

     using boost::intrusive_ptr<ObjectT>::operator->; 
     using boost::intrusive_ptr<ObjectT>::get; 

     typedef const ObjectT* (PtrB::*unspecified_bool_type)() const; 

     operator unspecified_bool_type() const 
     { 
      const ObjectT* p = boost::intrusive_ptr<ObjectT>::get(); 
      if (p != NULL) 
      { 
       printf("ptr is not null\n"); 
      } 

      return p == 0 ? 0 : (unspecified_bool_type)&PtrB::get; 
     } 
}; 

int main() 
{ 
    // this verison compiles 
    // PtrA<Object> obj(new Object()); 

    PtrB<Object> obj(new Object()); 

    if (obj == NULL) 
    { 
     printf("object is null\n"); 
    } 
    if (!obj) 
    { 
     printf("object is null\n"); 
    } 
    return 0; 
} 

대신 공개 bool 관용구? 내가 이름 검색의 규칙을 변경하지 않습니다 GCC에게 4.8.5

+0

@WhiZTiM OP의 예제를 수정했습니다. 주석 처리 된 행을 변경하면됩니다. – Barry

+0

@ 배리, 오 ... 장님 ... 그래. .. 재현. 대답에 대한 설명이 나와 있습니다. :-) – WhiZTiM

답변

4

If boost intrusive ptr is privately inherited, what does GCC tries to use it instead the public bool idiom?

개인 inhertiance를 사용합니다. 액세스 할 수없는 변환이 필요한 경우 결과적으로 최적의 실행 가능한 후보를 형편 없게 만듭니다. 이 경우, 이러한 작업을하고있는 :

if (obj == NULL) 
if (!obj) 

하는 작업도

operator unspecified_bool_type() 통해 간다. 전자는 다음을 찾습니다.

그리고 후자는 intrusive_ptr<T>::operator!()을 찾습니다. 그것들은 그 두 가지 작전을위한 가장 유력한 후보자입니다. 연산자는 사용자 정의 변환 시퀀스이지만 intrusive_ptr이 제공하는 연산자는 표준 변환 시퀀스입니다. 그러나이 두 가지는 PtrB<T>에서 intrusive_ptr<T>으로의 변환을 필요로합니다.

+0

답변 해 주셔서 감사합니다. 이 문제를 어떻게 극복 할 생각이 있습니까? 나는 연산자를 다시 구현하려고 시도했다. 및 조작자 bool. 하지만 연산자 == (이 경우에는 호출되지 않아야 함)에 여전히 문제가 있습니다. – michael

+0

@michael 왜 전화가 안되니? 당신은'=='을 쓰고 있습니다. 그러나'intrusive_ptr' 호출을 원하지 않는다면, 직접 작성해야합니다. – Barry

+0

네가 맞다. 방해받지 않는 ptr에는 nullptr_t를받는 연산자 ==가있다. 감사! – michael