Reputation: 2243
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
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