2016-08-14 71 views
2

我試圖用我自己的ptr包裝提升侵入性ptr,它將投射重載到布爾。另外,在我的ptr中,我想限制訪問某些助推入侵ptrmethods。起初,我使用了boost intrusive ptr作爲我的ptr的私有成員,並使用了bool成語,並且它運行良好並使用了bool成語。 由於我自己的特殊原因,在某些時候我需要將新的ptr作爲boost intrusive ptr的類型,所以我使用了私有繼承,但那不起作用。出於某種原因,gcc試圖將我的ptr作爲一種助推入侵的ptr,並拒絕使用公開暴露的bool慣用法。 這裏是演示了一個示例代碼是:海灣合作委員會將私人繼承到父母

#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; 
} 

編譯錯誤在此代碼的結果使用的ptrB:

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>' 

如果升壓侵入PTR是私有繼承,什麼是GCC嘗試使用它而不是公共布爾成語? 我用gcc 4.8.5

+0

@WhiZTiM我修正了OP的例子 - 你只需要改變哪一行是註釋。 – Barry

+0

@Barry,Ohhh ...讓我失明...是的..轉載。你的答案解釋了它。 :-) – 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()。前者發現:

template<class T, class U> 
bool operator==(intrusive_ptr<T> const & a, U * b); 

而後者發現intrusive_ptr<T>::operator!()。這些是這兩個行動最可行的候選人。您的操作員將是用戶定義的轉換序列,但intrusive_ptr提供的轉換序列是標準轉換序列。但是這兩個要求從PtrB<T>intrusive_ptr<T>的轉換,這是使它們不合格的。

+0

謝謝你的回答!你有一個想法如何克服這個問題?我試圖重新實現運營商!和運算符布爾。但是我仍然對operator ==有問題(在這種情況下不應該調用它)。 – michael

+0

@michael爲什麼不應該被稱爲?你正在寫'=='。但如果你不想調用'intrusive_ptr',你只需要編寫自己的。 – Barry

+0

你是對的,我沒有看到侵入ptr有一個運算符==它接收nullptr_t。謝謝! – michael

相關問題