Search code examples
c++templatesoperator-overloadingfriend

Complicated operator overloading and templates


This is an extremely mad implementation of fixed-point arithmetic in C++. Please, no comments on how bad and pointless all this is.

As you can see, there is a base type T and a number of binary digits for the fractional part N. It is needed that FixedNum<int, A> + FixedNum<int, B> evaluated to FixedNum<int, MAX(A, B)>. Here is how I try to implement it. However, GCC says that the assignments to x in the last lines are wrong, as x is protected. What's wrong?

#define MAX(a,b) (((a)>(b))?(a):(b))

template <typename T, int N>
class FixedNum
{
    public:
        template <int N2>
        friend FixedNum& operator+(const FixedNum& f, const FixedNum& g);
        template <int N2>
        friend FixedNum& operator+=(const FixedNum& f, const FixedNum& g);
        FixedNum(T x): x (x) {}

        T num() const { return x; }
        int point() const { return N; }

    protected:
        T x;
};

template <typename T, int N, int N2>
FixedNum<T, MAX(N, N2)>& operator+(const FixedNum<T, N>& f, const FixedNum<T, N2>& g)
{
    return FixedNum<T, N>(f) += g;
}

template <typename T, int N, int N2>
FixedNum<T, MAX(N, N2)>& operator+=(const FixedNum<T, N>& f, const FixedNum<T, N2>& g)
{
#if N2 <= N
    f.x += g.x << (N-N2);
#else
    f.x <<= (N2-N);
    f.x += g.x;
#endif
}

Solution

  • Each instantiation of a template class type is a different class.
    Remember that the classes actually have a different name, and are not related by inheritance.

    FixedNum<int,5> is a unique name, and will be different from the class type FixedNum<int,6>.
    Therefor they can't access each other's protected members.

    You will have to decalare all the "similar" templated classes as friends, like this:

    template<typename T, int N> friend class FixedNum;
    

    Besides that, using preprocessor #if over there won't work like you want it to.
    The preprocessor, much like its name, process BEFORE the compiler starts to process all the code. So it only evaluates MACRO values and prprocessor definitions.