Страницы

Поиск по вопросам

среда, 5 февраля 2020 г.

Перегрузка шаблонных операторов с разделением на описание и имплементацию

#cpp #шаблоны_с++


Есть класс Vector2, шаблонный. 

template 
class Vector2
{
public:
    // ...
    friend Vector2 operator*(ConstAddress> l_v, ConstAddress r_val);
    // ...
}

// ...

template
Vector2 operator*(ConstAddress> l_v, ConstAddress r_val)
{ return Vector2(l_v._x * r_val, l_v._y * r_val); }


ConstAddress - это моё собственное извращение, но в целом это то же самое, что
и const T&.

При попытке скомпилировать выдаёт ошибку  


  undefined reference to `operator*(Vector2 const&, float const&)'

    


Ответы

Ответ 1



(Тема всплывает с заметной периодичностью.) В качестве "друга" вы объявили нешаблонную функцию operator *. А определение ваше сделано для шаблона функции operator * - оно к вашему "другу" никакого отношения не имеет. Для оператора-друга вы не предоставили определения вообще, а именно его и пытается вызвать компилятор. Получается ошибка линковки. (Если вы заставите компилятор вызвать именно шаблонную версию оператора, определенную после класса, то вы наткнетесь на другую ошибку: "другом" эта версия оператора не является и доступа к внутренним полям класса не имеет.) Либо объявите шаблон функции в качестве "друга" template class Vector2 { ... template friend Vector2 operator *(ConstAddress> l_v, ConstAddress r_val); ... }; template Vector2 operator *(ConstAddress> l_v, ConstAddress r_val) { return Vector2(l_v._x * r_val, l_v._y * r_val); } Либо перенесите определение вашего оператора прямо в тело класса - чтобы оно определяло правильную нешаблонную функцию. (Если я не ошибаюсь, синтаксиса для того, чтобы сделать это за пределами класса в С++ просто нет.) template class Vector2 { ... friend Vector2 operator *(ConstAddress> l_v, ConstAddress r_val) { return Vector2(l_v._x * r_val, l_v._y * r_val); } ... }; В первом случае вы получите то, что я называю "ленивым" набором объявлений - все версии шаблонного оператора (для всех U) получат "дружбу" со всем версиями шаблонного класса (для всех T). Возможен также третий вариант - "неленивый" вариант шаблонного объявления, который несколько более громоздок, в котором "дружба" получится только между соответствующими (по шаблонному параметру) версиями шаблонного оператора и шаблонного класса. См. по ссылкам: Доступ к привату через friend Ссылка на неразрешенный внешний элемент

Комментариев нет:

Отправить комментарий