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

C++ C++;所有类型的模板类朋友,c++,templates,friend,C++,Templates,Friend,我有一个向量类,我重载了操作符* 我希望能够将浮点向量与int向量相乘 我有以下代码,但当我编译他的时候,我有一个错误,因为我没有访问私有字段的权限 模板 类向量机 { 模板友类向量机; 私人: int m_维; T*m_值; } 样板 T1操作员*(常数向量和v1、常数向量和v2) { 断言(v1.m_维度==v2.m_维度); T res=T(); 对于(int i=0;i

我有一个向量类,我重载了操作符*

我希望能够将浮点向量与int向量相乘

我有以下代码,但当我编译他的时候,我有一个错误,因为我没有访问私有字段的权限

模板
类向量机
{
模板友类向量机;
私人:
int m_维;
T*m_值;
}
样板
T1操作员*(常数向量和v1、常数向量和v2)
{
断言(v1.m_维度==v2.m_维度);
T res=T();
对于(int i=0;i
我也试过了,但我可以访问v1的私有字段,但不能访问v2的私有字段

模板
类向量机
{
私人:
int m_维;
T*m_值;
样板
友元T运算符*(常数向量和v1,常数向量和v2)
{
断言(v1.m_维度==v2.m_维度);
T res=T();
对于(int i=0;i
您的第一个版本声明了
Vecteur的一个特化
是另一个的朋友。这无助于您的操作员
*
,因为他仍然不是朋友,无法访问私人成员

向量中为模板重载添加正确的好友声明(并且您不需要为专门化添加好友):

模板
类向量机{
//...
模板标准::通用类型
友元运算符*(常量向量和,常量向量和);
//...
};
//而不是声明后的定义

或者,您可以将专门化作为朋友,并添加
操作符*
作为成员,但我不喜欢这样,因为这样的重载操作符可以更干净地实现为独立函数。

当您迫切需要将函数或类声明为类的朋友时,花点时间看看你的设计,问问自己这是否绝对必要

在发布代码的情况下,不要试图解决与授予
friend
-ship给
操作符*
函数相关的问题,而是为类的数据提供访问器函数,完全不需要授予
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;
}
模板
类向量机
{
公众:
int getDimensions()常量{return m_dimensions;};
T&运算符[](std::size_T i){返回m_值[i];};
常量和运算符[](std::size_T i)常量{返回m_值[i];};
私人:
int m_维;
T*m_值;
};
//不需要成为班级的朋友。
样板
typename std::common_type::type operator*(常量向量&v1,常量向量&v2)
{
断言(v1.getDimensions()==v2.getDimensions());
typename std::common_type::type res{};
对于(int i=0;i
你期望什么
模板朋友类向量
要做什么?@FrançoisAndrieux,当然,但是
操作符*
不是-在这个例子中它是一个独立的函数。@FrançoisAndrieux我知道它的意思。我在问OP他们的意图是什么最初,我的代码是第二个。我在其他帖子中看到了第一个。我想找一个能访问Vecteur和VecteurTank的私有字段的操作符*,它非常有效,但我不确定我是否理解std::common_type_t,我尝试用T1代替它,我得到了相同的结果。你可能正在用int向量乘以float向量。只有T1,您将得到整数结果(而float将是一个理想的结果),这对我来说不起作用。使用std::common_type\t,我还可以得到一个int向量,如果我将int向量与float向量相乘,这很糟糕,我没有在函数的代码中用std::common_type\t替换T1。没关系,看我之前的消息。谢谢,我知道这一点,但我只需要与朋友合作来提高我的知识。我不同意。向其他内部成员提供访问器是没有意义的。您现在将内部细节暴露给外部世界,也可以将成员公开。独立函数在逻辑上是接口(和契约)的一部分,友好是一种更好的方法。@SergeyA,显然,我们有不同的软件开发方法。+1完全同意:向量(在物理/数学上)应该让公众不断访问其组件。
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;
}