2

Есть примерно такой код:

comandSource.h

#pragma once

#include <iostream> #include <math.h> #include <assert.h>

using namespace std;

namespace mth { template <typename T> class Vector { private: unsigned int length = 0; T* buffer = NULL;

public:
    Vector();
    Vector(const Vector &amp;r);
    Vector(int _length);
    ~Vector() { delete[] buffer; }

    void print();
    unsigned int len() { return length; }
    friend T dot_product(const Vector&lt;T&gt;&amp; v1, const Vector&lt;T&gt;&amp; v2)
    /*{
        T res = 0;
        assert(v1.length == v2.length &amp;&amp; &quot;The array lengths must be equal&quot;);

        for (unsigned int i = 0; i &lt; v1.length; ++i)
            res += v1.buffer[i] * v2.buffer[i];

        return res;
    }*/;

    Vector operator = (const Vector&amp; source);
    Vector operator + (const Vector&amp; other);    
    T&amp; operator [] (const unsigned int index);
    friend Vector&lt;T&gt; operator-&lt;&gt;(const Vector&lt;T&gt;&amp; v1, const Vector&lt;T&gt;&amp; v2);
};



template &lt;typename T&gt;
Vector&lt;T&gt;::Vector():
    Vector(1)
{}

template &lt;typename T&gt;
Vector&lt;T&gt;::Vector(int _length):
    length(_length)
{
    buffer = new T[length];
    for (unsigned int i = 0; i &lt; length; i++)
        buffer[i] = 0;
}

template &lt;typename T&gt;
Vector&lt;T&gt;::Vector(const Vector &amp;arg):
    length(arg.length)
{   
    buffer = new T[length];
    for (unsigned int i = 0; i &lt; length; i++)
        buffer[i] = arg.buffer[i];
}

template&lt;typename T&gt;
void Vector&lt;T&gt;::print()
{
    cout &lt;&lt; &quot;{ &quot;;
    for (unsigned int i = 0; i &lt; length; i++)
        cout &lt;&lt; &quot;'&quot; &lt;&lt; buffer[i] &lt;&lt; &quot;' &quot;;
    cout &lt;&lt; &quot;}\n&quot;;
}

template&lt;class T&gt;
T dot_product(const Vector&lt;T&gt;&amp; v1, const Vector&lt;T&gt;&amp; v2)
{
    T res = 0;
    assert(v1.length != v2.length &amp;&amp; &quot;The arrays lengths must be equal&quot;);

    for (unsigned int i; i &lt; v1.length; ++i)
        res += v1.buffer[i] * v2.buffer[i];

    return res;
}

template&lt;typename T&gt;
Vector&lt;T&gt; Vector&lt;T&gt;::operator=(const Vector&amp; source)
{
    length = source.length;
    buffer = new T[length];

    for (unsigned int i = 0; i &lt; length; i++)
        buffer[i] = source.buffer[i];

    return *this;
}

template &lt;typename T&gt;
Vector&lt;T&gt; Vector&lt;T&gt;::operator+(const Vector&amp; arg)
{
    if (length != arg.length)
    {
        cout &lt;&lt;&quot;[ERROR] vectors doesn't match by size&quot;&lt;&lt;endl;
        exit(1);
    }

    Vector&lt;T&gt;temp(length);
    for (unsigned int i = 0; i &lt; length; i++)
        temp.buffer[i] = buffer[i] + arg.buffer[i];

    return temp;
}

template&lt;typename T&gt;
T&amp; Vector&lt;T&gt;::operator[](const unsigned int index)
{
    assert(index &gt;= 0 &amp;&amp; index &lt; length &amp;&amp; &quot;Invalid array index&quot;);
    return buffer[index];
}

template&lt;typename T&gt;
Vector&lt;T&gt; operator-(const Vector&lt;T&gt;&amp; v1, const Vector&lt;T&gt;&amp; v2)
{
    assert(v1.length == v2.length &amp;&amp; &quot;The array lengths must be equal&quot;);

    Vector&lt;T&gt; temp(v1.length);
    for (unsigned int i = 0; i &lt; v1.length; i++)
        temp.buffer[i] = v1.buffer[i] - v2.buffer[i];

    return temp;
}

}

Пишу в main

mth::Vector<int> example(2);
    mth::Vector<int> example2(2);
example[0]=1;
example[1]=2;

example2[0]=5;
example2[1]=8;
cout &lt;&lt; mth::dot_product(example, example2) &lt;&lt; endl;

Выдает ошибки типа такой, по одной на каждое обращение к члену.

mth::Vector<int>::length: невозможно обратиться к private член, объявленному в классе "mth::Vector<int>"

Как так, если функция дружественная? Причем, если определить функцию в теле класса, а не снаружи, то все работает.

И еще вопрос касательно синтаксиса c++, не создавать же для такой ерунды отдельную тему: Почему для перегрузки через метод мы можем писать как

(const Vector& source)

так и

(const Vector<T>& source)

А для перегрузки через дружественную функцию работает только так?

(const Vector<T>& v1, const Vector<T>& v2)

Я про <T> в параметрах

Harry
  • 221,325

1 Answers1

5

Объявите в классе

template<typename U> friend
U dot_product(const Vector<U>& v1, const Vector<U>& v2);

вместо вашего

friend T dot_product(const Vector<T>& v1, const Vector<T>& v2);

У вас дружественная функция - шаблон...

Harry
  • 221,325
  • Действительно, а я человеку дичь всякую советую)) – vp_arth Oct 24 '20 at 17:56
  • Спасибо, только интересно, в чем проблема дружественной функции использовать тот же – Alrond2198 Oct 24 '20 at 18:05
  • Потому что это не тот же T, вообще говоря. Это свой шаблонный параметр, не связанный с T. Там есть какая-то хитрость, она разбиралась на ruSO, надо искать - как сделать дружественную функцию дружественной только для того же параметра типа; откровенно говоря, я ее не помню. Здесь же функция дружественная для всех типов, независимо от того, что в классе, что в типе. – Harry Oct 24 '20 at 18:07
  • Ага, например вот - https://ru.stackoverflow.com/a/511301/195342 и https://ru.stackoverflow.com/a/700315/195342. – Harry Oct 24 '20 at 18:14