2016-08-14 3 views
2

私はブールへのキャストをオーバーロードする私自身のptrで侵入型ptrをラップしようとしていました。さらに、私のptrでは、いくつかのboost侵入型ptrmethodsへのアクセスを制限したいと思います。最初は私のptrのプライベートメンバーとしてブースト介入ptrを使用し、boolイディオムを使用しました。それはうまくいき、boolイディオムを使用しました。 私自身の特別な理由から、新しいptrが侵入型のptrを増強する必要があったので、私は私的継承を使用しましたが、それはうまくいきませんでした。何らかの理由でgccが私のptrを、侵入型のptrとして処理しようとし、公開されているboolイディオムを使用することを拒否します。GCCは私的継承を親に変換します

#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!()を見つけます。これらは、これらの2つの事業にとって最も実行可能な候補です。演算子はユーザ定義の変換シーケンスですが、intrusive_ptrが提供するものはスタンダード変換シーケンスです。しかし、これらの2つはPtrB<T>からintrusive_ptr<T>への変換を必要とし、それがそれらを不正な形にする。

+0

あなたの答えをありがとう!あなたはこの問題を克服する方法を知っていますか?私は演算子を再実装しようとしました!オペレータブール。しかし、私はまだoperator ==(この場合は呼び出されないはずです)に問題があります。 – michael

+0

@michaelなぜ呼び出されないのですか?あなたは '=='と書いています。しかし、 'intrusive_ptr'が呼び出されないようにするには、あなた自身で書く必要があります。 – Barry

+0

あなたは正しいです、私は侵入的なptrがnullptr_tを受け取る演算子==を持っているのを見ませんでした。ありがとう! – michael

関連する問題