如何制作抽象模板类的矢量

时间:2013-07-11 07:59:55

标签: c++ templates vector virtual abstract

以下不起作用:

std::vector<IRule*> vec;
RuleRangeDouble *rule = new RuleRangeDouble(0, 100);
vec.push_back(rule);

现在如何制作不同规则的载体?我知道,我必须使用指针...但是我还需要做些什么才能让它工作?如何更改我的基础结构以使其工作?

我使用如下界面:

// Interface
    template <typename T>
    class IRule
    {
        public:
            virtual bool isValid(T value) = 0;
    };

我的示例类看起来像这样:

class RuleRangeDouble : public IRule<double>
    {
        private:
            double min;
            double max;
        public:

            bool isValid(double value)
            {
....
            };
    };

2 个答案:

答案 0 :(得分:3)

向量需要是实际类型的向量,例如std::vector<IRule<double>*>Irule本身不是一个类型,它是一个类模板。所以你需要

std::vector<IRule<double>*> vec;
RuleRangeDouble *rule = new RuleRangeDouble(0, 100);
vec.push_back(rule);

如果模板参数不是接口的一部分,则可以引入公共基类。不要忘记给它一个virtual析构函数:

class IRule
{
    public:
        virtual bool isValid(T value) = 0;
        virtual ~IRule() {}
};

template <typename T>
class Rule : public IRule 
{
  .....
};

class RuleRangeDouble : public Rule<double>
{
  ....
};

然后您的原始用例示例将起作用:

std::vector<IRule*> vec; // IRule really is a type now
RuleRangeDouble *rule = new RuleRangeDouble(0, 100);
vec.push_back(rule);

答案 1 :(得分:2)

您可以通过多种方式实现getBestValidValue()之类的内容。一种是定义一个特殊的通用(但非模板)返回类型用于getBestValidValue(),也作为isValid(value)的参数类型(juanchopanza的答案在这里有错误):

class ValueType
{
  enum { is_int, is_double } my_type;  // add more if you want
  union { my_int; my_double; };        // union only works for simple types
public:
  // implicit construction from allowed types
  ValueType(int x) : my_type(is_int), my_int(x) {}
  ValueType(double x) : my_type(is_double), my_double(x) {}
  // use SFINAE for is<type>() function
  template<typename T>
  typename std::enable_if<std::is_same<T,int>::value,bool>::type
  is() const { return my_type==is_int; }
  template<typename T>
  typename std::enable_if<std::is_same<T,double>::value,bool>::type
  is() const { return my_type==is_double; }
  // implicit type conversion to allowed types
  // note: does not assert(is<T>())
  operator int() { return my_int; }
  operator double() { return my_double; }
};

class IRule
{
public:
  virtual bool isValid(ValueType const&) const = 0; // fixed bug in juanchopanza's answer
  virtual ValueType getBestValidValue() const = 0;  // return any type of value
  virtual ~IRule() {}
};

template<typename T>
class Rule : public IRule
{
protected:
  virtual bool valid(T) const = 0; 
  virtual T bestValidValue() const = 0;
public:
  bool isValid(ValueType const&value) const
  {
    return value.is<T>()
        && valid(value);         // implicit type conversion to T
  }
  ValueType getBestValidValue() const
  {
    return bestValidValue();     // implicit construction of ValueType
  }
  ....
}