Название: Перегрузка бинарных операторов для шаблонного класса Отправлено: schmidt от Октябрь 29, 2013, 00:36 Доброй ночи, уважаемые,
Перегруженные бинарные операторы для обычных классов полезно делать вне класса, объявляя их как friend, чтобы компилятор мог справиться с выражением Код: Type1_object + Type2_object независимо от порядка операндов. Тем же путем иду сейчас при разработке шаблонного класса, но сталкиваюсь с проблемами - компилятор не может подхватить реализацию оператора вне класса: Код: template <class T> Но при использовании его в коде компилятор жалуется, что не может найти подходящий оператор для вызова с такими аргументами Цитировать undefined reference to `operator+(AtdVector<int>::iterator const&, unsigned int)' а также указывает на существующую реализацию оператора в качестве кандидата Цитировать candidates are: template<class T> const typename AtdVector<T>::iterator& operator+(const typename AtdVector<T>::iterator&, typename AtdVector<T>::size_type) note: template argument deduction/substitution failed: note: couldn't deduce template parameter 'T' Почесав в затылке, я понял, что оператор при такой реализации оказался отдельной шаблонной функцией, не зависящей от исходного шаблонного класса. Манера использования шаблонных функций предписывает вызывать их так: Код: templateFunction<Type>(...); Что совсем не вписывается в привычную работу с операторами. Есть ли варианты, как можно укротить шаблоны и добиться для них привычного использования бинарных операторов в стиле "a+b и ничего лишнего"? Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: Igors от Октябрь 29, 2013, 09:41 Код: template <class C> Код: typename AtdVector<T>::size_type step Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: mutineer от Октябрь 29, 2013, 10:08 Цитировать undefined reference to `operator+(AtdVector<int>::iterator const&, unsigned int)' А почему компилятор считает второй параметр интом? Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: _Bers от Октябрь 29, 2013, 22:01 Код: template <class T> Для начала представьте полностью компилирующийся код, который содержит объявление шаблона, и функцию main. Реализацию дружественной функции можно пока не указывать. Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: m_ax от Октябрь 29, 2013, 22:58 Код: template <class T> Для начала представьте полностью компилирующийся код, который содержит объявление шаблона, и функцию main. Реализацию дружественной функции можно пока не указывать. Ну уж можно уж сообразить то: 1) MyVector { // <---- ошибка синтаксиса: непонятный символ: MyVector Очевидно, class MyVector 2) class iterator: // <---- ошибка синтаксиса: похоже на объявление класса, за которым должно последовать наследование. Скорее всего наследование от std::iterator, но это не принципиально.. 3) AtdVector<T>::iterator& iter, <---- ошибка синтаксиса: неопознанный символ AtdVector Несложно догадаться, что по сути это и есть MyVector.. опечатка.. А по сути, ошибка у ТС связана с тем, что в данном случае необходимо опережающее объявление шаблона функции.. Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: _Bers от Октябрь 29, 2013, 23:36 Ну уж можно уж сообразить то: Это не код, а одна сплошная опечатка. Я не телепат. Компилятор тоже не телепат. Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: schmidt от Октябрь 31, 2013, 06:34 Выбросил все несущественные моменты из кода, код можете посмотреть в прикрепленных файлах. Существенные моменты здесь таковы: 1. Чтобы определить перегруженный бинарный оператор с двумя аргументами он должен быть объявлен вне класса 2. Чтобы определить бинарный оператор для объектов шаблонного класса само собой он тоже должен быть как-то связан с параметром шаблона 3. Если в коде объявлена шаблонная функция, вызов ее принято писать как Код: templFunc<int>(...) Значит нужно либо как-то заставить компилятор создавать экземпляр оператора наряду с экземпляром шаблонного класса, либо... стрелять в разработчиков C++ шаблонов за то, что они сидят и в ус не дуют ;D Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: Igors от Октябрь 31, 2013, 11:10 Код: typedef unsigned int size_type; Также неясно к чему вся эта возня с "итератором", чем не устраивало простое T * ? Ведь контейнер явно линейный. Также не вижу кто/где заряжает _INIT_VECTOR_SIZE (да и не очень удачное имя для члена). В общем, как всегда, силенка ушла в "наведение песиков", а содержательная часть в пролете :) Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: m_ax от Октябрь 31, 2013, 13:11 Цитировать В общем, как всегда, силенка ушла в "наведение песиков", а содержательная часть в пролете :) Опять крайности.. ТС просто хочет разобраться с дружественными шаблонными операторами и этот пример нужно воспринимать просто как некий полигон ни больше ни меньше.. Цитировать Значит нужно либо как-то заставить компилятор создавать экземпляр оператора наряду с экземпляром шаблонного класса, либо... стрелять в разработчиков C++ шаблонов за то, что они сидят и в ус не дуют ;D Вначале лучше разобраться в более простом примере: дружественный оператор в шаблонном классе: Код
Обратите внимание на опережающее объявление class Iterator и дружественного оператора.. Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: schmidt от Октябрь 31, 2013, 13:20 С итератором ли, без, вопрос с перегрузкой бинарных операторов для шаблонных классов все равно актуален ) Хочу докопаться до сути и "отложить на полку, чтобы знать где достать", вместо того, чтобы потом судорожно и в матах копать этот вопрос, когда он будет необходим :)
В книге "C++ Templates: The Complete Guide" в разделе Friend Functions нашел информацию о том, что как только шаблонная функция объявлена как friend, ее экземпляр автоматически будет создан компилятором наряду с экземпляром шаблонного класса. Цитировать An instance of a function template can be made a friend by making sure the name of the friend function is followed by angle brackets. The angle brackets can contain the template arguments, but if the arguments can be deduced, the angle brackets can be left empty То есть теоретически объявления Код: template <class T> должно хватить, чтобы обеспечить ВСЕ экземпляры шаблонного класса оператором сложения. Однако на деле все оказывается совершенно вопреки написанному (выбросил уже ВСЕ что можно, оставив голый оператор сложения): Код: #ifndef TPLNUMBER_H Код: /* main.cpp */ При попытке компиляции: Цитировать /main.cpp:13: undefined reference to `operator+(TplNumber<int> const&, TplNumber<int> const&)' Какие еще могут быть извращенные варианты - ума не приложу... :) Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: m_ax от Октябрь 31, 2013, 13:33 Цитировать Какие еще могут быть извращенные варианты - ума не приложу... :) Вы как то не внимательно читаете чужие посты( У меня всё работает (найдите 10 отличий): Код
Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: schmidt от Октябрь 31, 2013, 14:15 Цитировать Вы как то не внимательно читаете чужие посты( ::) долго писал, видать, отправил, не увидел ваш пост :) Ммм, насчет 10 не уверен, но вот на этом месте Код: friend const TplNumber& operator+<>(const TplNumber& lhs, const TplNumber& rhs); Название: Re: Перегрузка бинарных операторов для шаблонного класса Отправлено: schmidt от Ноябрь 04, 2013, 11:21 *Убиться об стену*
А вот здесь http://www.parashift.com/c++-faq-lite/template-friends.html нашел, что, оказывается, все легко и просто :-\ : Код: template <class T> код френда объявляется прямо в классе, что делает все пляски с бубном абсолютно бессмысленными... //-------------------------------------------------------------------------------------------------------- P.S. Сделал вывод, что разносить объявление и определение шаблонных классов - ужасная и крайне вредная затея... ;D |