Что здесь происходит? - PullRequest
       36

Что здесь происходит?

3 голосов
/ 06 января 2012

Это не компилируется,

#include <boost/intrusive_ptr.hpp>

class X
{
public:
 void intrusive_ptr_add_ref(X* blah)
 {
 }

void intrusive_ptr_release(X * blah)
{
}

};



int main()
{
  boost::intrusive_ptr<X> ex(new X);
}

Но это делает:

#include <boost/intrusive_ptr.hpp>

class X
{
public:
  friend void intrusive_ptr_add_ref(X* blah)
  {
  }

  friend void intrusive_ptr_release(X * blah)
  {
  }

};



int main()
{
  boost::intrusive_ptr<X> ex(new X);
}

и это:

    #include <boost/intrusive_ptr.hpp>

    class X
    {
    public:


    };


    void intrusive_ptr_add_ref(X* blah)
      {
      }

      void intrusive_ptr_release(X * blah)
      {
      }

int main()
{
  boost::intrusive_ptr<X> ex(new X);
}

Я полагаю, что есть что-то делатьсо SFINAE (чего я еще не удосужился понять)?Помещает ли спецификатор друга определенную функцию в качестве свободной функции во вложенном пространстве имен?

edit

Кто бы ни удалил свой пост, функции-члены, не являющиеся друзьями, такие как add_ref и release (эти конкретные функции-члены не упоминаются в Документация ...) действительно решила проблему.Что происходит с вложенным определением с квалификатором friend?

1 Ответ

7 голосов
/ 06 января 2012

Из документации boost::intrusive_ptr:

Каждый новый экземпляр intrusive_ptr увеличивает счетчик ссылок, используя неквалифицированный вызов функции intrusive_ptr_add_ref, передавая ему указатель в качестве аргумента. Точно так же, когда intrusive_ptr уничтожается, он вызывает intrusive_ptr_release; эта функция отвечает за уничтожение объекта, когда его счетчик ссылок падает до нуля. Ожидается, что пользователь предоставит подходящие определения этих двух функций. На компиляторах, которые поддерживают поиск, зависящий от аргументов, intrusive_ptr_add_ref и intrusive_ptr_release должны быть определены в пространстве имен, которое соответствует их параметру; в противном случае определения должны быть расширены.

Это означает, что intrusive_ptr_add_ref и intrusive_ptr_release должны быть не функциями-членами, а свободными функциями (функции-друзья ведут себя как таковые). Более того, они вызываются без квалификации, поэтому они должны находиться в глобальном пространстве имен или где-то, найденном ADL.

Редактировать: На ваш вопрос о вложенных определениях с квалификатором friend: friend функции определены как функции, не являющиеся членами, поэтому friend void intrusive_ptr_add_ref(X* blah) будет называться intrusive_ptr_add_ref(my_x_ptr) вместо my_x_ptr->intrusive_ptr_add_ref().

...