【问题标题】:C++ intrusive_ptr issueC++ intrusive_ptr 问题
【发布时间】:2012-08-31 14:25:02
【问题描述】:

我想使用boost::intrusive_ptr 来引用我的类x::Y,所以我为releaseadd_ref 函数添加了references 字段和友元声明,它们应该在命名空间boost 中定义。然后,我编写这些函数。像这样:

namespace x{


    class Y{
        long    references;
        friend void boost::intrusive_ptr_add_ref(x::Y * p);
        friend void boost::intrusive_ptr_release(x::Y * p);
    };
}

namespace boost
{
    void intrusive_ptr_add_ref(x::Y * p)
    {
        ++(p->references);
    }

    void intrusive_ptr_release(x::Y * p)
    {
        if (--(p->references) == 0)
            delete p;
    }
}

代码无法编译,我收到以下错误:

test/test6.cpp:8:18: error: ‘boost’ has not been declared
test/test6.cpp:9:18: error: ‘boost’ has not been declared
test/test6.cpp: In function ‘void boost::intrusive_ptr_add_ref(x::Y*)’:
test/test6.cpp:7:11: error: ‘long int x::Y::references’ is private
test/test6.cpp:17:9: error: within this context
test/test6.cpp: In function ‘void boost::intrusive_ptr_release(x::Y*)’:
test/test6.cpp:7:11: error: ‘long int x::Y::references’ is private
test/test6.cpp:22:13: error: within this context

我以为我做了 boost 文档中解释的所有事情,但似乎我做错了什么。问题出在哪里?

【问题讨论】:

  • 为什么要侵入式引用计数? shared_ptr 这里有什么问题,因为您的课程最初没有被引用。
  • 请坚持这个问题。这只是解释我的问题的一个最小示例。

标签: c++ boost namespaces smart-pointers forward-declaration


【解决方案1】:

错误是因为您在类定义中引用了 boost 命名空间,在该命名空间的任何声明之前。您可以通过在类定义之前声明 namespace boost 来修复它;您还需要声明函数,为此您还需要声明类和命名空间:

namespace x {class Y;}
namespace boost
{
    void intrusive_ptr_add_ref(x::Y * p);
    void intrusive_ptr_release(x::Y * p);
}

但是,最好不要将函数放在 boost 命名空间中,而是放在包含您的类的命名空间中(即在 namespace x 中)。然后intrusive_ptr 将通过依赖于参数的名称查找找到正确的版本。这不需要在类之前进行任何声明。

【讨论】:

    【解决方案2】:

    在这个特定的最小代码中,您似乎遗漏了一些影响

    namespace x { class Y; }
    namespace boost {
            void intrusive_ptr_add_ref(x::Y * p);
            void intrusive_ptr_release(x::Y * p);
    }
    

    在一开始。也就是说,前向声明 Y 并声明您的函数。虽然你为什么要经历这种痛苦只是为了将你的函数放入它们不属于的名称空间中,这超出了我的理解。

    【讨论】:

      【解决方案3】:

      您需要转发声明它们。

      如果您的编译器支持 Argument Dependent Lookup,您应该将函数 intrusive_ptr_add_refintrusive_ptr_release 放入您自己的命名空间中,并在那里转发声明它们。

      namespace x{
          void intrusive_ptr_add_ref(x::Y * p);
      
          void intrusive_ptr_release(x::Y * p);
      
          class Y{
              long    references;
              friend void boost::intrusive_ptr_add_ref(x::Y * p);
              friend void boost::intrusive_ptr_release(x::Y * p);
          };
      
          void intrusive_ptr_add_ref(x::Y * p)
          {
              ++(p->references);
          }
      
          void intrusive_ptr_release(x::Y * p)
          {
              if (--(p->references) == 0)
                  delete p;
          }
      }
      

      编辑:如果您希望将它们放在 boost 命名空间中,您可以这样做,方法是在您的类之前转发声明带有这两个函数声明的 boost 命名空间。

      【讨论】:

        【解决方案4】:

        您可以在namespace x 中定义这些函数。但是如果你想在namespace boost 中声明函数,使用类似这样的东西

        #include <boost/intrusive_ptr.hpp>
        
        namespace x
        {
           class Y;
        }
        
        namespace boost
        {
            void intrusive_ptr_add_ref(x::Y * p);
            /*{
                ++(p->references);
            }*/
        
            void intrusive_ptr_release(x::Y * p);
            /*{
                if (--(p->references) == 0)
                    delete p;
            }*/
        }
        
        namespace x{
        
            class Y{
                long    references;
                friend void boost::intrusive_ptr_add_ref(x::Y * p);
                friend void boost::intrusive_ptr_release(x::Y * p);
            };
        }
        
        namespace boost
        {
            void intrusive_ptr_add_ref(x::Y * p)
            {
                ++(p->references);
            }
        
            void intrusive_ptr_release(x::Y * p)
            {
                if (--(p->references) == 0)
                    delete p;
            }
        }
        

        http://liveworkspace.org/code/99cb62380019ccb39993f0a9e656eff2

        【讨论】:

          【解决方案5】:

          第一个错误表明您没有包含任何提升标头。其余是因为第一个错误导致 friend 声明解析失败。

          【讨论】:

            【解决方案6】:

            如果你将intrusive_ptr_add_refintrusive_ptr_release 定义在与::x::Y 类相同的命名空间中,即在::x 中,它将起作用。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-12-04
              • 1970-01-01
              • 2018-06-08
              • 2012-04-09
              • 1970-01-01
              • 2021-06-10
              • 2011-02-23
              • 1970-01-01
              相关资源
              最近更新 更多