What can I do to make this work:
template<class C, class V, Test V::*>
class Test {
};
it gives me compiler error:
unknown type name 'Test'
It's a self-referencing template for now, which doesn't seem possible. What could possibly be done to make it work?
EDIT:
Here's what I'd need this for. I want to implement a bi-directional (think parent-child) relationship schema with the least minimum coding effort.
template <class O, class T, Reference<T, O, Reference O::*> T::* opposite>
class Reference
{
T **data;
int count;
public:
Reference(): data(new T*[N]), count(0) {}
~Reference() {delete[] data;}
Reference &add(T *t) {
handleOtherSide();
return link(t);
}
// a lot of stuff to implement this
};
That's the collection class. Here's how it would be used:
class Partner
{
public:
Reference<Partner, Address, &Address::partner> addresses;
};
class Address
{
public:
Reference<Address, Partner, &Partner::addresses> partner;
};
My goal is to have everything necessary for Reference to work be supplied as template argument, so that there is no need to provide constructors for classes like Partner and Address (currently I supply the opposite member pointer as a constructor arg but this requires me to have explicit constructors for the participant classes). I would also need to pass in or calculate an "owner" pointer to the Reference class. I left this problem out here because I want to focus on the self-referencing template aspect.
The easiest way to think of this is boost::bimap. But the problem with bimap is that I don't want the enclosing bimap but just the left and right part of it. bimap is also not feasible because it would lead to one single bimap managing all associations of a specific relationship. It would possibly hold a large number of objects slowing down operations on it.
Are you looking for something like this? It's not self-referencing template, but you can specify derived class as a template type for base class and base class can call derived methods etc.:
template< typename PType, typename PDerived >
class TBase
{
//do stuff with TDerived
public:
bool foo( void )
{
return ( static_cast< PDerived* > ( this )->bar() );
}
};
template< typename PType >
class TDerived : public TBase< PType, TDerived< PType > >
{
friend class TBase< PType, TDerived< PType > > ;
//do stuff
protected:
bool bar( void )
{
return ( true );
}
};
EDIT: Once again, I'm not sure what's your final goal. Here is a solution to what I think you want, or, at least, some hint to what you might use to implement your design. The only requirement that I put is that both TAddress
and TPartner
have function with same name. See if that's what you need. In principle, you can make a helper class and use CRTP to access member function through a pointer, but I don't think you actually need it.
template< typename PType1, typename PType2 >
class TReference
{
public:
int mFlag;
TReference() :
mFlag( 0 )
{
}
TReference( int fFlag ) :
mFlag( fFlag )
{
std::cout << "Creating reference " << PType1::sName << " -> " << PType2::sName << "." << std::endl;
}
TReference< PType2, PType1 > AccessOpposite( void )
{
PType2 lTmp;
lTmp.Opposite();
return TReference< PType2, PType1 > ( -1 );
}
};
class TPartner;
class TAddress
{
public:
static const char* sName;
TReference< TAddress, TPartner > mRef;
void Opposite( void )
{
std::cout << sName << "::Opposite" << std::endl;
}
};
class TPartner
{
public:
static const char* sName;
TReference< TPartner, TAddress > mRef;
TReference< TAddress, TPartner > Opposite( void )
{
std::cout << sName << "::Opposite" << std::endl;
}
};
const char* TAddress::sName = "TAddress";
const char* TPartner::sName = "TPartner";
int main( void )
{
TAddress lAddress;
TPartner lPartner;
std::cout << lAddress.mRef.mFlag << " " << lPartner.mRef.mFlag << std::endl;
lPartner.mRef = lAddress.mRef.AccessOpposite();
std::cout << lAddress.mRef.mFlag << " " << lPartner.mRef.mFlag << std::endl;
return ( 0 );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With