Функция друга шаблона класса шаблона - PullRequest
0 голосов
/ 02 июля 2018

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

Например, у меня есть следующий класс шаблона и функция друга шаблона:

template<int N>  class Matrix;
template<typename T, int N> Matrix<N> operator*(const Matrix<N> &m1, const T &m2);

// class definition
template<int N>
class Matrix{
  template<typename T>
  friend Matrix<N> operator* (const Matrix<N> &m1, const T &m2);
};

// friend function definition
template<typename T, int N> Matrix<N> operator*(const Matrix<N> &m1, const T &m2)
{
    return m1; // just as an example
}

Если я скомпилирую:

Matrix<3> m;
m * 1.0;

Я бы получил следующую ошибку компоновщика:

test.cc:(.text+0x1c7): undefined reference to `Matrix<3> operator*<double>(Matrix<3> const&, double const&)'
collect2: error: ld returned 1 exit status

1 Ответ

0 голосов
/ 02 июля 2018

У вас несоответствие в натуральном выражении.

Ваша первоначальная декларация и последующее определение имеют эту подпись:

template<typename T, int N>
Matrix<N> operator*(const Matrix<N> &m1, const T &m2);

Это шаблон функции, принимающий два параметров шаблона: T и N.

Однако в вашем классе вы создаете в качестве друга шаблон функции с такой подписью:

template<typename T>
friend Matrix<N> operator* (const Matrix<N> &m1, const T &m2);

Имеется только один параметр шаблона: T. N здесь зафиксировано. Это объявление друга также объявляет этот шаблон функции. Это лучшее соответствие, но на самом деле не определено, отсюда и поведение, которое вы видите.

<ч />

Думаю, у вас есть два варианта.

  1. Удалите объявление области имен пространства operator* и просто объявите и определите friended operator* в определении Matrix.

  2. Измените объявление друга, чтобы оно соответствовало объявлению пространства имен:

    template<typename T, int M>
    friend Matrix<M> operator* (const Matrix<M> &m1, const T &m2);
    

(1), как правило, является лучшим вариантом - не требует добавления большего числа operator* в глобальную область видимости, что хорошо для времени компиляции.

...