I am testing out a property system and I want to make sure that the root class can hold function pointers to the most derived class that there is. As a result I have something that is sort of working. The most derived class is currently working (RC2), but the current middle class (RC1) will have a compiler error. I want to be able to instantiate RC1 and RC2. The compiler error I will get with RC when creating it is (for the line of RC1<RC1> rc1test;
)
error C2955: 'RC1' : use of class template requires template argument list
error C3203: 'RC1' : unspecialized class template can't be used as a template argument for template parameter 'PropertyOwner', expected a real type
I tried to do RC1<> rc1test;
but that did not help either. Here is the source, does anyone have any suggestions?
#include <iostream>
#include <map>
#include <string>
using namespace std;
template<class T, class BaseClass>
class RBase : p开发者_运维百科ublic BaseClass
{
public:
typedef int (T::*GetFP)(void) const;
protected:
std::map<const char*, GetFP> mGetFPs;
};
class CBase
{
};
template<class PropertyOwner>
class RC1;
template<class PropertyOwner=RC1>
class RC1 : public RBase<PropertyOwner, CBase>
{
public:
int int1(void) const
{
return 1;
}
RC1()
{
mGetFPs.insert( pair<const char*, GetFP>("RC1I1I", &PropertyOwner::int1) );
};
virtual void inspection(void)
{
int test = 0;
}
};
class RC2 : public RC1<RC2>
{
public:
int int2(void) const
{
return 2;
}
RC2()
{
mGetFPs.insert( pair<const char*, GetFP>("RC2I2I", &RC2::int2) );
};
virtual void inspection(void)
{
int test = 0;
}
};
int main(void)
{
RC1<RC1> rc1test;
RC2 rc2test;
rc2test.inspection();
return(0);
}
If you can use boost then you might be able to do a cleaner approach using boost::function and boost::bind to get the pointers you want.
template <typename BC>
class RBase : public BC
{
public:
typedef int FunctionSignature (void) const;
typedef boost::function<FunctionSignature> CallbackFunction;
protected:
std::map<const char*, CallbackFunction> mGetFPs;
};
class CBase
{
};
class RC1 : public RBase<CBase>
{
public:
RC1 ()
{
mGetFPs.insert ( std::make_pair ( "RC1I1I",
boost::bind ( &RC1::int1, this ) ) );
}
int int1(void) const { return 1; }
};
class RC2 : public RC1
{
public:
RC2 ()
{
mGetFPs.insert ( std::make_pair ( "RC2I2I",
boost::bind ( &RC2::int2, this ) ) );
}
int int2(void) const { return 2; }
};
In fact, you can assign ANY function that has the proper signature to the boost::function and even use boost::bind to adapt functions that have additional parameters (see below).
class RC3 : public RC1
{
public:
RC3 ()
{
mGetFPs.insert ( std::make_pair ( "RC3I3I",
boost::bind ( &RC3::intN, this, 3 ) ) );
}
int intN(int n) const { return n; }
};
template<class PropertyOwner=RC1>
class RC1 /*...*/;
If there is a default argument for template type argument PropertyOwner
, it needs to be a type. RC1
is not a type. It is a class template.
精彩评论