Аргументы шаблона по умолчанию - PullRequest
0 голосов
/ 02 марта 2011

Я тестирую систему свойств и хочу убедиться, что корневой класс может содержать указатели функций на самый производный из существующих классов. В результате у меня есть кое-что, что работает. Самый производный класс в настоящее время работает (RC2), но текущий средний класс (RC1) будет иметь ошибку компилятора. Я хочу иметь возможность создавать экземпляры RC1 и RC2. Ошибка компилятора, которую я получу с RC при его создании (для строки RC1<RC1> rc1test;)

ошибка C2955: «RC1»: использование шаблона класса требует списка аргументов шаблона

ошибка C3203: «RC1»: шаблон специализированного класса нельзя использовать в качестве аргумента шаблона для параметра шаблона «PropertyOwner», ожидается реальный тип

Я пытался сделать RC1<> rc1test;, но это тоже не помогло. Вот источник, у кого-нибудь есть предложения?

#include <iostream>
#include <map>
#include <string>
using namespace std;

template<class T, class BaseClass>
class RBase : public 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);
}

Ответы [ 2 ]

1 голос
/ 03 марта 2011

Если вы можете использовать boost, тогда вы можете сделать более чистый подход, используя boost :: function и boost :: bind, чтобы получить нужные вам указатели.

    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; }
    };

Фактически, вы можете назначить ЛЮБУЮ функцию, которая имеет правильную сигнатуру, для boost :: function и даже использовать boost :: bind для адаптации функций, имеющих дополнительные параметры (см. Ниже).

    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; }
    };
1 голос
/ 02 марта 2011
template<class PropertyOwner=RC1>
class RC1 /*...*/;

Если есть аргумент по умолчанию для аргумента типа шаблона PropertyOwner, это должен быть тип.RC1 является не типом.Это шаблон класса.

...