C++ 模板 class 所有类型的朋友

C++ template class friend with all type

我有一个 Vector class 并且我重载了运算符*

我希望能够将 float 向量与 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;
    }
}

您的第一个版本声明了 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* 添加为成员,但我不喜欢这样,因为这样的重载运算符作为独立函数实现得更干净。

当您想要声明一个函数或 class 一个 class 的朋友时,花点时间看看您的设计并问问自己这是否绝对必要。

在发布代码的情况下,与其尝试解决与授予 friend-ship 给 operator* 函数相关的问题,不如为 [=18] 的数据提供访问函数=] 并完全摆脱授予 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;
}