开发者

Default template arguments

开发者 https://www.devze.com 2023-02-14 22:26 出处:网络
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.

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消