【问题标题】:GCC converts private inherited to parentGCC 将继承的私有转换为父级
【发布时间】:2016-08-14 18:49:47
【问题描述】:

我试图用我自己的 ptr 来包装 boost 侵入 ptr,这会使转换为 bool 过载。此外,在我的 ptr 中,我想限制对某些 boost 侵入 ptrmethods 的访问。起初我使用 boost intrusive ptr 作为我的 ptr 的私有成员并使用 bool 成语,它运行良好并使用了 bool 成语。 在某些时候,出于我自己的特殊原因,我需要新的 ptr 是 boost 侵入式 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>'

如果 boost intrusive ptr 是私有继承的,那么 GCC 会尝试使用什么来代替 public bool 习惯用法? 我使用 gcc 4.8.5

【问题讨论】:

  • @WhiZTiM 我修复了 OP 的示例 - 您只需更改注释的行。
  • @Barry,哦……瞎了我……是的……转载。您的回答说明了这一点。 :-)

标签: c++ inheritance gcc


【解决方案1】:

如果 boost intrusive ptr 是私有继承的,那么 GCC 会尝试用什么来代替 public bool idiom?

私有继承不会改变名称查找的规则。如果需要不可访问的转换,它只会使生成的最佳可行候选者格式错误。在这种情况下,您正在执行以下操作:

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&lt;T&gt;::operator!()。这些是这两项行动的最佳可行候选人。您的运算符将是一个用户定义的转换序列,但 intrusive_ptr 提供的是标准转换序列。但是这两个需要从PtrB&lt;T&gt;intrusive_ptr&lt;T&gt; 的转换,这就是它们格式错误的原因。

【讨论】:

  • 感谢您的回答!你知道如何克服这个问题吗?我尝试重新执行运算符!和运算符布尔。但是我仍然有 operator== 的问题(在这种情况下不应该被调用)。
  • @michael 为什么不应该调用它?你正在写==。但是,如果您不想调用 intrusive_ptr ,则只需编写自己的代码。
  • 你是对的,我没有看到侵入性 ptr 有一个 operator== 接收 nullptr_t。谢谢!
猜你喜欢
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-20
相关资源
最近更新 更多