Question

I am trying to write a C++ program which wraps numeric values, I am doing this by writing a super class which will handle two simple functions, and an operator overloading function. This is the code I have so far:

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



template <class T>
class Number {
protected:
    T number;

public:
    Number(T num) {
        number = num;
    }

    string mytype() {
        return typeid(number).name();
    }

    string what_am_i() {
        ostringstream oss;
        oss << "I am " << Number<T>::mytype() << " and my value is " << number;
        return oss.str();
    }

    Number operator+ (Number an) {
        Number brandNew = NULL;
        brandNew.number = number + an.number;
        return brandNew;
    }
};


class MyInt : public Number<int> {
public:
    MyInt() : Number<int>(0) {};
    MyInt(int num) : Number<int>(num) {}
    MyInt(const Number<int> &x) : Number<int>(x) {}
};



class MyFloat : public Number<float> {
public:
    MyFloat() : Number<float>(0){};
    MyFloat(float num) : Number(num){}
    MyFloat(const Number<float> &x) : Number<float>(x) {}   
};

class MyDouble : public Number<double> {
public:
    MyDouble() : Number<double>(0){};
    MyDouble(double num) : Number(num){}
    MyDouble(const Number<double> &x) : Number<double>(x) {}    
};

In the main function I would like to do something like :

void main() {       
    MyInt two = 2;       
    MyFloat flo = 5.0f;
    MyDouble md3 = flo + two;
}

And wish for md3 to be 15.00000, up to now an addition of two objects from the same type works great but when I am trying to add a MyInt and MyFloat the compiler doesn't like it. Does anyone have an idea how could I implement this?

Was it helpful?

Solution

You have to add the type operator for your template class:

operator T()
{
    return number;
}

This is the complate code that I tested and work:

template <class T>
class Number {
protected:
    T number;

public:
    Number(T num) {
        number = num;
    }

    string mytype() {
        return typeid(number).name();
    }

    string what_am_i() {
        ostringstream oss;
        oss << "I am " << Number<T>::mytype() << " and my value is " << number;
        return oss.str();
    }

    Number operator+ (Number an) {
        Number brandNew = NULL;
        brandNew.number = number + an.number;
        return brandNew;
    }

    operator T()
    {
        return number;
    }
};

I try to explain better why it works. When you make overloading of the plus operator, you want to do something like: left_value + right_value, where right_value is the "an" argument of the plus operator.

Now to get the right value of your object "an", you have to overloading the "type operator", if you don't make overloading of this operator inside your Number class it can not be read as a right value. The following example is for the operator=(), but is valid also for operator+():

template<typename T>
class Number
{
  T value;

  public:

  T operator=(T arg) // Assignment, your class is seen as left operand
  {
    value = arg;
  }

  operator T() // Getting, your class is seen as right operand
  {
     return value;
  } 
}

Number<int>     A;  // define a new class Number as int
Number<double>  B;  // define a new class Number as double

A = B; // is same to A.operator=( B.double() );

to assign A as left value is called the operator "operator=()" of the class Number, while to get B as right value is called the "operator T()" of the class Number

Now this is translated as:

// instance of the operator = of the class Number<int>
int operator=(int arg)
{
}


// instance of the Operator T of the class Number<double>
operator double()
{
}

this traslation emulates the follwoing semantic for A and B object:

int A;
double B;

A = B;

Ciao Angelo

OTHER TIPS

You may specify the result of a binary operation and use a freestanding operator:

#include <iostream>
#include <typeinfo>

template <class T>
class Number {
template <typename>
friend class Number;

protected:
    T number;

public:
    Number(const T& num)
    :   number(num)
    {}

    template <typename U>
    Number(const Number<U>& num)
    :   number(num.number)
    {}

    // ...

    const T& value() const { return number; }
};

typedef Number<int> MyInt;
typedef Number<float> MyFloat;
typedef Number<double> MyDouble;

template <typename A, typename B>
struct NumberResult;

template <typename X>
struct NumberResult<X, X> {
    typedef X type;
};

template <> struct NumberResult<int, float> { typedef float type; };
template <> struct NumberResult<float, int> { typedef float type; };
// ...

template <typename A, typename B>
inline Number<typename NumberResult<A, B>::type>
operator + (const Number<A>& a, const Number<B>& b) {
    return Number<typename NumberResult<A, B>::type>(a.value() + b.value());
}

Note: Please avoid using namespace std; in a header.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top