gexicide
gexicide

Reputation: 40088

C++ intrusive_ptr issue

I want to use boost::intrusive_ptr for refcounting my class x::Y, so I add a references field and friend declarations for the release and add_ref functions, which should be defined in namespace boost. Then, I write those functions. Like this:

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

The code does not compile, I receive the following errors:

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

I thought I did everthing like explained by the boost documentation, but it seems that I did something wrong. Where is the problem?

Upvotes: 0

Views: 2866

Answers (6)

bobah
bobah

Reputation: 18864

It will work if you define intrusive_ptr_add_ref and intrusive_ptr_release in the same namespace as the class ::x::Y, namely in ::x.

Upvotes: 0

Mike Seymour
Mike Seymour

Reputation: 254621

The errors are because you are referring to the boost namespace in your class definition, before any declaration of that namespace. You can fix it by declaring namespace boost before your class definition; you'll also need to declare the functions, and to do that you'll also need to declare the class and namespace:

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

However, if might be better to put the functions not in the boost namespace, but in the namespace containing your class (i.e. in namespace x). Then intrusive_ptr will find the correct version by argument-dependent name lookup. This doesn't require any declarations before the class.

Upvotes: 3

ForEveR
ForEveR

Reputation: 55897

You can define these functions in namespace x. But if you want to declare functions in namespace boost, use something like this

#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

Upvotes: 1

Dave S
Dave S

Reputation: 21123

You need to forward declare them.

If your compiler supports Argument Dependent Lookup, you should put the functions intrusive_ptr_add_ref and intrusive_ptr_release into your own namespace, and forward declare them there as well.

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

Edit: If you would prefer to put them in the boost namespace, you can do that instead, by forward declaring the boost namespace with those two function declarations in it prior to your class.

Upvotes: 1

Michael Krelin - hacker
Michael Krelin - hacker

Reputation: 143219

In this particular minimal code, you seem to be missing something to the effect of

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

in the beginning. That is, forward-declare Y and declare your functions. Though why would you want to go through this pain just to put your functions into the namespace where they do not belong is beyond me.

Upvotes: 2

MSalters
MSalters

Reputation: 179981

The first errro suggests that you didn't include any boost headers. The remainder is because that first error causes parse failures on the friend declarations.

Upvotes: 0

Related Questions