Question

I created a class template (called ThreeVector) and added functionality to allow the addition operation between different types. Here's the relevant portion of my header file:

template <class T>
class ThreeVector {
    private:
        T mx;
        T my;
        T mz;
        public:
        ThreeVector<T>(T, T, T);
            template <class X> 
        ThreeVector<T> operator+(const ThreeVector<X>&);
}

template <class T> 
ThreeVector<T>::ThreeVector(T x, T y, T z) { //initialize vector
    mx = x;
    my = y;
    mz = z;
}

template<class T> template<class X>
ThreeVector<T> ThreeVector<T>::operator+(const ThreeVector<X>& a) {
    ThreeVector<T> v(mx+a.mx, my+a.my, mz+a.mz);
    return v;
}

And then I call it like this:

ThreeVector<double> a(1,2,3);
ThreeVector<float> b(4,5,6);
ThreeVector<double> c=a+b;

This gives me the error:

ThreeVector.h: In member function 'ThreeVector<T> ThreeVector<T>::operator+(const ThreeVector<X>&) [with X = float, T = double]':
ThreeVectorTest.cxx:33:   instantiated from here
ThreeVector.h:8: error: 'float ThreeVector<float>::mx' is private
ThreeVector.h:122: error: within this context
ThreeVector.h:9: error: 'float ThreeVector<float>::my' is private
ThreeVector.h:123: error: within this context
ThreeVector.h:10: error: 'float ThreeVector<float>::mz' is private
ThreeVector.h:124: error: within this context
make: *** [ThreeVectorTest] Error 1

It works fine if both a and b are <double>. Any idea why this happens?

Was it helpful?

Solution

The access privileges of class templates can be a little confusing.

Say you have a simple class template.

template <typename T>
class A
{
   public:
      A() {}

   private:
      T data;
};

When you create instances of A using,

A<int> a1;
A<float> a2;

You are defining two classes using the template. It's as if you had two classes:

class AInt
{
   public:
     AInt() {}
   private:
     int data;
};

and

class AFloat
{
   public:
     AFloat() {}
   private:
     float data;
};

It's easy to see that AInt doesn't have access to the private section of AFloat and vice versa.

That is also true with A<int> and A<float>.

In order for you make your operator+ function work, you have two choices:

  1. Make the members of the class template public.
  2. Have a friend declaration like:

    template <class T>
    class ThreeVector {
       private:
          T mx;
          T my;
          T mz;
       public:
          ThreeVector<T>(T, T, T);
    
          template <class X> 
             ThreeVector<T> operator+(const ThreeVector<X>&);
    
          template <class X> friend class ThreeVector;
    };
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top