Domanda

I have an interface IOperand :

class IOperand
{
   public:
     virtual IOperand * operator+(const IOperand &rhs) const = 0;
     virtual std::string const & toString() const = 0;
}

And the class Operand :

template <class T>
class Operand : public IOperand
{
   public:
     virtual IOperand * operator+(const IOperand &rhs) const;
     virtual std::string const & toString() const;
     T    value;
}

The IOperand class and the members functions operator+ and toString prototype cannot be modified. The member function operator+ has to add 2 values contained in 2 IOperand. My issue is that this value can be an int, a char or a float but I don't know how to do that with templates. I have tried this :

template <typename T>
IOperand *              Operand<T>::operator+(const IOperand &rhs) const
{
  Operand<T> *op = new Operand<T>;
  op->value = this->value + rhs.value;
  return op;
}

my toString method :

template <typename T>
std::string const &     Operand<T>::toString() const
{
  static std::string s;  // Provisional, just to avoid a warning for the moment
  std::ostringstream convert;
  convert << this->value;
  s = convert.str();
  return s;
}

But the compiler does not find this->value and rhs.value because they're not in IOperand.

EDIT : As advice in the comments, I added the toString method in Operand and Ioperand, I don't really know if it could help.

È stato utile?

Soluzione

Welcome to the wonderful word of binary operators. What do you want to happen when you do this:

IOperand* foo = new Operand<Matrix<Complex>>;
IOperand* bar = new Operand<Polynomial<FiniteField<5>>>;
IOperand* baz = *foo + *bar;

?

There are basically two possible answers. You want a compilation error, or you want a runtime error. The latter is easily doable with a dynamic_cast, the former is easily doable by throwing away your design, taking a CS university course, then PhD, then creating your own theory of binary operations and inventing your own OO language.

Of course don't neglect mundane things like memory leaks while doing all that.

Altri suggerimenti

If IOperand is really untouchable, you'll have to resort to dynamic_cast:

template <typename T>
IOperand * Operand<T>::operator+(const IOperand &rhs) const
{
  if (const Operand<T> *arg = dynamic_cast<const Operand<T>*>(&rhs))
  {
    Operand<T> *op = new Operand<T>;
    op->value = this->value + arg->value;
    return op;
  }
  else
    return NULL;  // Or any other sensible "error occured"
}

The dynamic_cast will succeed only if rhs is actually an instance of the same Operand<T> as the one on which operator + is called. This is then checked in the if.

However, let me state that this is horrible design. Operators should be overloaded to behave as much as the built-in ones as possible (unless you're using them in domain-language style). Using + on std::strings doesn't result in a pointer to a dynamically allocated std::string either.

Code legibility aside, the primary reason why it's so wrong is that it's very easy to leak memory - the only sensible implementation of this operator+ will allocate memory dynamically, and since it returns a raw pointer, it's left up to the caller to ensure that memory is not leaked. Bad stuff.

define IOperandas template class with typename T

add T get_value() in class IOperand should work,

overload this function Operand, so you can fetch the data defined in child class

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top