【问题标题】:Default template arguments默认模板参数
【发布时间】:2011-03-02 19:16:29
【问题描述】:

我正在测试一个属性系统,我想确保根类可以保存指向存在的最派生类的函数指针。结果,我有一些可以工作的东西。派生最多的类当前正在工作 (RC2),但当前的中间类 (RC1) 会出现编译器错误。我希望能够实例化 RC1 和 RC2。创建 RC 时我会遇到的编译器错误是(RC1<RC1> rc1test; 行)

错误 C2955:“RC1”:使用类模板需要模板参数列表

error C3203: 'RC1' : unspecialized class template can't be used as a template argument for template parameter '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);
}

【问题讨论】:

  • 要让 Stackoverflow 将文本视为代码,请在每行之前添加四个空格。
  • 要在stackoverflow上格式化代码,只需缩进四个空格。或者粘贴一些代码,突出显示它,然后按{} 按钮。
  • 完成 :-) 要查看未格式化的版本,请单击 edit

标签: c++ templates reflection properties metaprogramming


【解决方案1】:

如果您可以使用 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; }
    };

【讨论】:

  • 为什么 "boost::bind ( &RC3::intN, this, 3 )" 中有 3?我以为 3 是为了参数的数量?
  • 实际上,绑定中的“3”是调用 mGetFPS["RC3I3I"].second() 时将作为参数传递给 intN 的值。这是一个示例,说明如何实际使用 boost::bind 来调整在其签名中具有额外参数的函数。我猜“3”的值是不幸的。
【解决方案2】:
template<class PropertyOwner=RC1>
class RC1 /*...*/;

如果模板类型参数PropertyOwner 有默认参数,则它必须是类型。 RC1 不是一种类型。它是一个类模板。

【讨论】:

  • 您对代码上下文有什么建议吗?我认为它会将 RC1 视为一种类型。
猜你喜欢
  • 1970-01-01
  • 2013-02-28
  • 1970-01-01
  • 2015-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多