IAE
IAE

Reputation: 2243

C++ FAQ Lite Smart_Ptr Class Not Functioning?

I'm currently doing a lot of things on exception safety. (Herb Sutter's Exceptional C++, C++ FAQ Lite, etc)

In particular, I wanted to write and understand the reference counting example of C++ FAQ Lite, but I'm currently stuck on this part of the code:

class Smart_Ptr;

class Foo
{
private:
    friend class Smart_Ptr;
    unsigned int count_;

public:
    static Smart_Ptr create() // Error here.
    {
        return new Foo();
    }

private:
    Foo()
        : count_(0)
    { }

/* ... */
/* Smart_Ptr class initialized down here */

As you can see, I'm trying to use the Named Constructor Idiom to force the user not to create local variables of my Foo object. Essentially, this is exactly what is written in the C++ FAQ; I have merely changed Fred to Foo and FredPtr to Smart_Ptr, which I realize was a mistake because it's harder to see the connection now.

My compiler spits out the error:

error C2027: use of undefined type 'Smart_Ptr'

I'm not exactly sure why this is. Smart_Ptr is fully defined and a complete duplicate of the FAQ code. I have also copied the code in full, as is, and have received the same error.

End Crucial Part of Question

Since I keep mistakingly thinking I post 'enough' of the source code to debug the problem, and I keep ending up in the wrong, I will post the rest of the code here.

/* Foo.h */
class Smart_Ptr;

class Foo
{
private:
    friend class Smart_Ptr;
    unsigned int count_;

public:
    static Smart_Ptr create()
    {
        return new Foo();
    }

private:
    Foo()
        : count_(0)
    { }
};

class Smart_Ptr
{
private:
    Foo *p_; // p_ is NEVER null

public:
    Foo *operator-> () { return p_; }
    Foo& operator*  () { return *p_; }

    Smart_Ptr(Foo *p) 
        : p_(p)
    {
        ++p_->count_;
    }

    ~Smart_Ptr()
    {
        if (--p_->count_ == 0)
            delete p_;
    }

    Smart_Ptr(Smart_Ptr const& p)
        : p_(p.p_)
    {
        ++p_->count_;
    }

    Smart_Ptr& operator= (Smart_Ptr const& p)
    {
        Foo *const old = p_;
        p_ = p.p_;
        ++p_->count_;

        if (--old->count_ == 0)
            delete old;

        return *this;
    }
};

Upvotes: 2

Views: 580

Answers (1)

Steve Jessop
Steve Jessop

Reputation: 279455

You can't write a function that returns Smart_Ptr by value, until Smart_Ptr is defined. A forward declaration isn't enough.

The code you link to contains the comment, // Defined below class FredPtr {...};, but you have defined the create function in the Foo class definition. If you look closely at the code after "the changes to class Fred would be:", you'll see that create is only declared in the class: it's defined later, by the following code:

inline FredPtr Fred::create()             { return new Fred(); }

All you need is to do the same.

Upvotes: 4

Related Questions