Название: operator[] via get/set Отправлено: Eugene Efremov от Май 12, 2007, 03:22 Дано:
Код:
Требуется: Пользуясь этими ф-циями реализовать перегрузку оператора []: Код:
Такое вообще возможно? добавлено спустя 26 минут: Так... Я тормоз. Вот ответ: Код:
В реальных примерах, конечно, Mediator будет содержать и ссылку на тот класс, которому эти геттеры/сеттеры принадлежат. Не говоря уже о том, что надо пользоваться const &... Но это все уже детали. Задача решена, тему можно закрывать. ;-) Название: Re: operator[] via get/set Отправлено: Eugene Efremov от Апрель 06, 2008, 20:53 Так его разтак... Гладко было на бумаге. :-E
Попробовал внедрить это дело в реальном проекте: Код: template<class cont_tp, class key_tp, class val_tp> class access_operator И что получаем? Конструкции вида foo[ i].bar() не работают — в классе access_operator нет метода bar. И языковых средств, позволяющих объяснить компилятору, что в таком случае нужно преобразовывать его в val_tp — тоже нет: operator. не перегружается. А если пару таких контейнеров вложить друг в друга, выяснится, что foo[ i][ j] тоже не работает... А посему — вопрос снова в силе: Можно ли реализовать subj так, чтобы при этом ничего не отваливалось? Название: Re: operator[] via get/set Отправлено: Вячеслав от Апрель 06, 2008, 21:42 Абстрагируясь от вопроса 'а на кой это сдалось'
http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4031/ (http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4031/) http://www.codeproject.com/KB/cpp/genericproperty.aspx (http://www.codeproject.com/KB/cpp/genericproperty.aspx) http://forum.shelek.ru/index.php/topic,3887.0.html (http://forum.shelek.ru/index.php/topic,3887.0.html) Но IMHO оно того не стоит ...... Название: Re: operator[] via get/set Отправлено: Eugene Efremov от Апрель 06, 2008, 22:54 Абстрагируясь от вопроса 'а на кой это сдалось' В любой ситуации, когда мы не можем прочитать/записать объект напрямую, а должны что-то еще с ним сделать. Если он shared, нужно делать глубокое копирование перед изменением, если он хранится в где-то в сериализованном виде — его нужно "разархивировать". А может вообще никакого объекта нет и мы его создаем налету... Вариантов может быть много. http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4031/ (http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4031/) http://www.codeproject.com/KB/cpp/genericproperty.aspx (http://www.codeproject.com/KB/cpp/genericproperty.aspx) http://forum.shelek.ru/index.php/topic,3887.0.html (http://forum.shelek.ru/index.php/topic,3887.0.html) Спасибо, только там примерно то же самое, что и у меня, разве что более развернуто... Похоже, это единственный вменяемый способ реализовать такое в этом языке. :-/ Вообще, как я понял, проблема в том, что вызов метода — это не та операция, которую можно описать в терминах сеттеров/геттеров. Нужно добавить в интерфейс контейнера метод modify_item, возвращающий неконстантную ссылку. И юзать в этой ситуации именно его. А раз operator. не перегружается, придется вместо него юзать operator->. Криво, но, видимо, делать нечего... Название: Re: operator[] via get/set Отправлено: Eugene Efremov от Апрель 07, 2008, 01:50 А вот для случая foo[ i][ j] (где foo[ i] — объект с перегруженным operator[]) я попрежнему хорошего решения не вижу. В текущем варианте приходится писать foo[ i]->operator[](j), что не есть рулез.
Так что вопрос «можно ли сделать лучше?» остается в силе... Название: Re: operator[] via get/set Отправлено: Tonal от Апрель 07, 2008, 08:07 Я бы сделал как минимум 2е версии класса - одну для простых объектов, вторую для массивов, с переопределённым operator[].
В этом случае запись foo[ i][ j] как раз канает. Для доступа к членам - перегрузка operator* и operator->. Так что получается 4 класса: для простых значений (int, char, float...), для массивов простых значений, для сложных значений (структуры, классы), для массивов сложных значений. Хотя вопрос остаётся - зачем всё это громоздить, если есть get_item, set_item? И кроме того, кроме индексации есть итераторы - может в их сторону стоит посмотреть? :-) P.S. В принципе, вместо 4х отдельных шаблонов, всё это можно реализовать в одном конечном шаблоне используя type_traits и enable_if. Название: Re: operator[] via get/set Отправлено: Вячеслав от Апрель 07, 2008, 18:31 В любой ситуации, когда мы не можем прочитать/записать объект напрямую, а должны что-то еще с ним сделать. Если он shared, нужно делать глубокое копирование перед изменением, если он хранится в где-то в сериализованном виде — его нужно "разархивировать". А может вообще никакого объекта нет и мы его создаем налету... Вариантов может быть много. Хм .... Это уже жабу напоминает .... или нечто скриптовое ..... Я пробывал в одном из проектов использовать эту методу - быстро забил - так-как слишком много геморря с поддержкой работоспособности конструкций :( Если глянуть в глубь и ширь - то кажись первопроходцем был Borland - в 5 BC (VDBT) там был какой-то дикий гибрид шаблонов\препроцессора,ну а далее BCB с расширениями языка и MS с их declspec .... IMHO пока это не введут на уровне языка стандартом - нуегонафик - геморру больно много :(PS - а на vdbt наверное можно поглядеть - оно ведь работало ;) Название: Re: operator[] via get/set Отправлено: Eugene Efremov от Апрель 08, 2008, 03:19 Хотя вопрос остаётся - зачем всё это громоздить, если есть get_item, set_item? Ну конечно, это "синтаксический сахар", как и любая другая перегрузка операторов. И разумеется, без него можно обойтись. Но с ним удобнее. Я бы сделал как минимум 2е версии класса - одну для простых объектов, вторую для массивов, с переопределённым operator[]. В этом случае запись foo[ i][ j] как раз канает. Для доступа к членам - перегрузка operator* и operator->. Так что получается 4 класса: для простых значений (int, char, float...), для массивов простых значений, для сложных значений (структуры, классы), для массивов сложных значений. Ммм... Или я не врубаюсь, или тут написано про что-то сильно другое. У меня operator* отлично работает (gcc 3.4.5 и msvc 8, борланд с ваткомом пролетают — туда им и дорога) без перегрузки. С простыми значениями и их массивами никаких проблем нет. С указателями на классы тоже. Проблемы с вызовом методов классов имеются, но лечатся перегрузкой operator-> — и здесь действительно приходится писать специализацию для указателей, потому что иначе эта перегрузка их ломает. Проблема только с классами, в которых переопределен operator[]. Переопределить его в общем случае проблематично, поскольку мы не знаем заранее тип его возвращаемого значения. Т.е. мы можем, допустим добавить в access_operator<cont_tp,key_tp,val_tp> такой метод: Код: template<class key_other> int& operator[](const key_other& k) Код: template<class key_other, class val_other> val_other operator[](const key_other& k) Собственно, в этом и есть проблема. Если есть идеи, как заставить компилятор распознать это самое возвращаемое значение — буду рад их услышать... P.S. В новой версии стандарта, 0х которая, для таких вещей, кажется, есть ключевое слово auto. Но оно еще когда будет... Название: Re: operator[] via get/set Отправлено: Eugene Efremov от Апрель 08, 2008, 04:12 Так, еще не уверен, но, кажется, нашел подходящее решение:
http://rsdn.ru/Forum/message/2683272.flat.aspx Попробую использовать что-нибудь в этом роде... Название: Re: operator[] via get/set Отправлено: Eugene Efremov от Апрель 08, 2008, 06:45 Блин.... йя идиотъ... Достаточно потребовать, чтобы в контейнере был определен value_type с помощью typedef...
Остается, конечно, случай, когда вложенный контейнер "чужой". И вот для этого, как раз, и пригодятся извраты в стиле упомянутого auto_cast. Но это уже экзотика... Название: Re: operator[] via get/set Отправлено: Tonal от Апрель 08, 2008, 08:05 Ты же код не предоставил, поэтому я не в курсе, что ты уже реализовал и оно у тебя работает, а что нет. :)
Теперь вспоминаем о таких операторах как ++, += и чешем репу - так ли сладок этот сахар. :) Кстати, в реализациях багланда и MSVC, свойства (расширения языка) не поддерживали эти операторы. P.S. На rsdn-е довольно много обсуждались свойства на C++ - вроде даже статья есть... P.P.S С моей точки зрения, свойства - несколько облегчают написание, но усложняют отладку и поддержку (с ходу не понятно к чему приведёт простое присвоение, и ломаются всяческие подсказки). Что перевесит - решать тебе, но я бы не стал извращаться. :) |