Reputation: 113
I'm trying to use the pimpl idiom to hide some grungy template code, but I can't give derived classes of the body class friend access to the handle class. I get an error C2248 from MSVC 9 sp1. Here's some code to duplicate the error:
//
// interface.hpp
//
namespace internal{
template<class T>
class specific_body;
}
class interface
{
struct body;
body *pbody_;
interface(body *pbody);
template<class T>
friend class internal::specific_body;
public:
~interface();
interface(const interface &rhs);
bool test() const;
static interface create( bool value );
};
//
// interface.cpp
//
struct interface::body
{
virtual ~body(){}
virtual bool test() const = 0;
virtual interface::body *clone() const = 0;
};
class true_struct {};
class false_struct {};
namespace internal {
template< class T>
class specific_body : public interface::body
{ // C2248
public:
specific_body(){}
virtual bool test() const;
virtual interface::body *clone() const
{
return new specific_body();
}
};
bool specific_body<true_struct>::test() const
{
return true;
}
bool specific_body<false_struct>::test() const
{
return false;
}
} //namespace internal
interface::interface(body *pbody) : pbody_(pbody) {}
interface::interface(const interface &rhs) : pbody_(rhs.pbody_->clone()) {}
interface::~interface() { delete pbody_; }
bool interface::test() const
{
return pbody_->test();
}
interface interface::create(bool value )
{
if ( value )
{
return interface(new internal::specific_body<true_struct>());
}
else
{
return interface(new internal::specific_body<false_struct>());
}
}
//
// main.cpp
//
// #include "interface.hpp"
//
int _tmain(int argc, _TCHAR* argv[])
{
interface object( interface::create(true));
if ( object.test() )
{
// blah
}
else
{
}
return 0;
}
Any help would be appreciated, I'm trying to hide interface::body
and specific_body
implementations from the users of interface
if that's not obvious from my question.
Upvotes: 1
Views: 1586
Reputation: 113
Well, I was able to "solve" this problem by making the body
a public declaration in the interface. That solves the C2248 error during the declaration of the specific_body
. I also made the body
a friend to the interface
class and added a method to the body
struct:
static interface create( body *pbody )
{
return interface(pbody);
}
so that a specific_body
can create an interface
if there is a nested relationship between instances of specific_body
Upvotes: 0
Reputation: 6439
You need to add template<> in the explicit instantiation of the template test method
template<> // add this line
bool specific_body<true_struct>::test() const
{
return true;
}
Upvotes: 1
Reputation: 28097
In addition to the unqualified specific_body mentioned by Troubadour, your specialization attempt of specific_body<>::test for true_struct and false_struct seems incorrect. You have to specialice the full class.
To solve the problem, I'd simply declare body in the public section. Declaring specific_body to be a friend of interface::body in addition doesn't help either.
Upvotes: 0
Reputation: 1
Try using typename maybe? I think I read in Sutter that typename will work to get to class inside of an unknown scope, while class won't.
Upvotes: 0
Reputation: 13421
You haven't qualified specific_body
. Try
template<class T>
friend class internal::specific_body;
as your friend declaration.
Upvotes: 0