C ++ шаблон класса друг со всеми типами - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть класс Vector и я перегружаю оператор *

Я хотел бы иметь возможность умножить вектор с плавающей запятой на Vector of int.

У меня есть следующий код, нокогда я его компилирую, у меня появляется ошибка, потому что у меня нет доступа к приватным полям.

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;
}

Я тоже пробовал это, но я могу получить доступ к приватным полям v1, но не к приватным полям 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 ]

0 голосов
/ 13 февраля 2019

Если у вас есть желание объявить функцию или класс другом класса, найдите время, чтобы взглянуть на свой дизайн и спросите себя, действительно ли это необходимо.

В случае опубликованного кодавместо того, чтобы пытаться решить проблему, связанную с предоставлением friend -ship для функции operator*, предоставьте функции доступа к данным класса и избавьтесь от необходимости вообще предоставлять friend -ship.

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;
}
0 голосов
/ 13 февраля 2019

Ваша первая версия объявляет одну специализацию Vecteur другом другой.Это не поможет вашему оператору *, поскольку он все еще не является другом и не может получить доступ к закрытым членам.

Добавьте правильную декларацию друга для перегрузки шаблона в вашем Vecteur (и вам это не нужноДруг специализации):

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

В качестве альтернативы, вы можете добавить специализацию и добавить operator* в качестве члена, но мне это не нравится, поскольку такие перегруженные операторы более четко реализованы как автономные функции.

...