-1

I have a Vector class and I overload the operator*

I would like to be able to multiply a Vector of float with a Vector of int.

I have the following code but when I compile him, I have an error because I don't have access to private fields.

template <class T>
class Vecteur
{
    template <class U> friend class Vecteur;

private:
    int m_dimensions;
    T *m_values;
}

template<class T1, class T2>
T1 operator*(const Vecteur<T1> &v1, const Vecteur<T2> &v2)
{
    assert(v1.m_dimensions == v2.m_dimensions);
    T res = T();
    for (int i = 0; i < v1.m_dimensions; i++)
    {
        res += v1.m_values[i] * v2.m_values[i];
    }
    return res;
}

I also tried this but I can access to private fields of v1 but not to the private fields of v2

template <class T>
class Vecteur
{
private:
    int m_dimensions;
    T *m_values;

    template<class T2>
    friend T operator*(const Vecteur<T> &v1, const Vecteur<T2> &v2)
    {
        assert(v1.m_dimensions == v2.m_dimensions);
        T res = T();
        for (int i = 0; i < v1.m_dimensions; i++)
        {
            res += v1.m_values[i] * v2.m_values[i];
        }
        return res;
    }
}

2 Answers2

1

Your first version declares one specialization of Vecteur a friend of another. This doesn't help your operator *, since this is still not a friend and can't access private members.

Add proper friend declaration for template overload in your Vecteur (and you do not need to friend the specialization):

template<class T>
class Vectuer {
//...
template<class T1, class T2> std::common_type_t<T1, T2>
friend operator*(const Vecteur<T1>& , const Vectuer<T2>& );
//...
};

// And than a definition after the declaration

Alternatively, you can friend the specialization, and add operator* as a member, but I do not like this, since such overloaded operators are more cleanly implemented as freestanding functions.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
0

When you have the urge to declare a function or a class a friend of a class, take moment to look at your design and ask yourself whether that is absolutely necessary.

In the case of the posted code, instead of trying to solve the problem associated with granting friend-ship to the operator* function, provide accessor functions to the data of the class and get rid of the need for granting friend-ship altogether.

template <class T>
class Vecteur
{
   public:

      int getDimensions() const { return m_dimensions; };
      T& operator[](std::size_t i) { return m_values[i]; };
      T const& operator[](std::size_t i) const { return m_values[i]; };

   private:
    int m_dimensions;
    T *m_values;
};

// Does not require to be a friend of the class.
template<class T1, class T2>
typename std::common_type<T1, T2>::type operator*(const Vecteur<T1> &v1, const Vecteur<T2> &v2)
{
    assert(v1.getDimensions() == v2.getDimensions());

    typename std::common_type<T1, T2>::type res{};
    for (int i = 0; i < v1.getDimensions(); i++)
    {
        res += v1[i] * v2[i];
    }
    return res;
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thank you, I know this but I just need to work with friend to improve my knowledge – Steeven Tronet Feb 13 '19 at 18:59
  • I disagree. There is no point in giving accessors to otherwise internal members. You are now exposing inner details to outside world, and might just as well make the member public. Friendship for standalone functions, which are logically a part of interface (and contract) is a much better approach. – SergeyA Feb 13 '19 at 19:06
  • @SergeyA, we, obviously, have different approaches to software development. – R Sahu Feb 13 '19 at 19:11
  • +1 completely agree: a vector (in the physical/mathemathical sense) should give public constant access to its components. – Walter Feb 13 '19 at 21:57