| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > property в c++ |
| Автор: Ivan. 18.8.2011, 19:15 | ||||
| Здравствуйте коллеги. Уже несколько лет я возвращаюсь к мысли как же все таки реализовать проперти в сях. Все время упираюсь во всяческие ограничения компиляторов и т.п. и вот наконец решил, может не самый идеальный вариант, но все же не плохой. ЗАДАЧА: Основная задача - это уйти от всяческих конструкторов, дополнительных переменных и максимально оптимизировать код на скорость, объем и удобство применения и вот что у меня получилось: 1. Оптимизация - здесь все отлично, оптимизируется все на этапе компиляции и при работе ни чем не отличается от прямого доступа; 2. Применение - здесь тоже не плохо, можно прикреплять что угодно, хоть к полю родителя, хоть проперти на проперти, да хоть самого на себя зациклить можно; 3. Описание - здесь чуть похуже, но все равно не плохо: а) необходимость прописать класс хозяина или мутатора. б) разные дефайны для описания нужного проперти. А в остальном не больше чем в настоящем __property; 4. Память - так как мой проперти является структурой, а многие компиляторы описывают пустую структуру минимум в один байт, то каждое проперти будет занимать по 1 байту. Эту проблему я решил описанием всех пропертей в union, то есть в худшем случаи все протепря займут в сумме 1 байт в классе; 5. Ну и наконец сама реализация - всего 15 строчек дефайнов. КОД:
ОПИСАНИЕ: PROPERTY_BEGIN - начало блока пропертей. PROPERTY_END - конец блока пропертей. Объявление проперти: PROPERTY_GS - с getter-ом и setter-ом PROPERTY_GW - с getter-ом и прямым доступом записи в поле PROPERTY_RS - с прямым доступом чтения поля и setter-ом PROPERTY_RW - с прямым доступом чтения поля и прямым доступом записи в поле PROPERTY_G - только с getter-ом PROPERTY_R - только с прямым доступом на чтение PROPERTY_S - только с setter-ом PROPERTY_W - только с прямым доступом на запись остальные дефайны служебные ПРИМЕР ПРИМЕНЕНИЯ:
ВЫВОДЫ: Как видите привязаться можно к чему угодно, хоть к проперти родителя и оптимизируется на ура. Если обнаружите ошибки или новые идеи - пишите. |
| Автор: boostcoder 18.8.2011, 19:35 | ||
| инициатива не должна быть наказуема! поэтому держи пять но давайте лучше посмотрим на препроцессированный код:
|
| Автор: Ivan. 18.8.2011, 19:41 |
| и что в нем не то? ну раскрыл ты дефайны, тебя это пугает? в итоге при компиляции это все сводится к нулю |
| Автор: boostcoder 18.8.2011, 19:47 |
| меня ничего не пугает. смотрю и думаю... |
| Автор: mes 18.8.2011, 20:04 |
что привлекло с беглого взгляда: попробуйте наследоваться от вашего класса с пропертями множественным наследованием, при этом Ваш класс должен быть не первым.. |
| Автор: Ivan. 18.8.2011, 20:22 |
| хотел проверить, но еще не успел. также нужно сделать проперти [] и закрыть операторы копии |
| Автор: Ivan. 19.8.2011, 08:56 | ||
Результат: в Tclass1::Ffoo = 1 (так как переменная volatile) в Tclass1::Ffoo = 3 в Tclass2::Ffoo = 4 Действие t.foo2 = 2; пропустил за ненадобностью, потому что оно тут же перекроется новыми значениями 4. Вывод: с множественным наследованием работает прекрасно |
| Автор: Alca 19.8.2011, 10:40 |
| А в бусте что нет пропертей? |
| Автор: boostcoder 19.8.2011, 10:47 |
нет |
| Автор: bsa 20.8.2011, 22:09 |
| Более того, в свое время Борланд пыталась их пропихнуть в стандарт. Но не приняли. |
| Автор: Ivan. 21.8.2011, 19:12 | ||
| ни как не могу придумать реализацию проперти с индексом. идея такая:
остается вопрос, как передать Index? |
| Автор: mes 21.8.2011, 20:10 | ||
может так ?
|
| Автор: Ivan. 21.8.2011, 21:16 |
| интересно, но это уже не проперти, если вместо [] придется использовать (), и все равно не получится реализовать сеттер |
| Автор: mes 21.8.2011, 21:17 |
ну так поставьте оператор [] Добавлено @ 21:20 сейчас подумаю.. Добавлено @ 21:24 вам надо возвращать не ссылку на _Val , а временный прокси-объект хранящий индекс в себе |
| Автор: Ivan. 22.8.2011, 11:01 | ||||
придумал:
раскрою дефайны, чтобы было понятней:
в итоге опять же все оптимизируется на этапе компиляции и ни чем не отличается от прямого вызова мутаторов. |
| Автор: Alca 22.8.2011, 12:09 | ||
Было бы неплохо убрать PROPERTY_BEGIN и PROPERTY_END:
|
| Автор: Ivan. 22.8.2011, 12:31 |
не получается по следующим причинам: 1. пустая структура во многих компиляторах равна 1 байту. (100 пропертей займет 100 байт в классе). для этого все проперти объединены в union. 2. нельзя получить относительный адрес объекта внутри объявления этого объекта. для этого в начало union-на помещена структура с именем __PROP, по которой определяется смещение родителя от проперти. Добавлено через 1 минуту и 30 секунд еще ни как не могу вспомнить флаг компилятора позволяющий преобразовывать указатель метода к void*, чтобы уйти от статических мутаторов |
| Автор: Ivan. 22.8.2011, 13:06 | ||
да, я понимаю. по этому такой флаг есть не во всех архитектурах. в билдере это не актуально, так как там есть настоящий проперти, в IAR_ARM указатель на метод равен 8 байтам, а вот в WIN_AVR такой флаг есть и указатель на метод равен указателю на данные. |
| Автор: Ivan. 22.8.2011, 13:52 | ||
вот что получилось на данный момент:
|
| Автор: Ivan. 24.8.2011, 16:58 | ||||
| Выяснилось, что описывать статические мутаторы не нужно. видимо когда я пытался решить эту задачу через темплейты я уперся в это ограничение и подумал, что это засада, а при реализации через дефайны в этом необходимость отпала. ИТОГО все свелось к следующему:
Примет:
При рассмотрении ассемблера: В поле t.FVal помещено значение 1; Действие t.Val2 = t.Val1; было проигнорировано, так как это копирование самого себя, а переменная не является volatile; Действие t.Array[10] = t.Val3; было проигнорировано, так как Index лежит за пределами массива FArray; В PORTB выдан 0, так как по условию, если Index лежит за пределами массива - getter возвращает 0. Остались следующие неудобства: - необходимость описывать блок пропертей; - разные дефайны для описания разных пропертей; - и необходимость описывать название класса хозяина проперти. |
| Автор: mes 24.8.2011, 18:19 |
а что заменить это внутренним тайпдефом разве не получается ? |
| Автор: Ivan. 24.8.2011, 18:54 |
приведи пример пожалуйста. что то в голову ничего не идет |
| Автор: mes 24.8.2011, 19:36 | ||
что то типа :
|
| Автор: Ivan. 25.8.2011, 10:20 |
| ну то есть вынести в объявление блока пропертей - логично |
| Автор: Ivan. 25.8.2011, 11:29 | ||||
обновленный вариант:
пример:
|
| Автор: boostcoder 10.9.2011, 12:00 |
| Ivan., я так понял, что при использовании проперти совместно с массивами, без гетера и сетера не обойтись? Добавлено через 5 минут и 15 секунд думаю, что все же нужна возможность использовать проперти совместно с массивами но без гетера и сетера. |
| Автор: boostcoder 10.9.2011, 12:34 |
| при использовании http://www.boost.org/doc/libs/1_47_0/libs/type_traits/index.html и http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error, вместо макросов: PROPERTY_GS, PROPERTY_GW, PROPERTY_RS, PROPERTY_RW, PROPERTY_G, PROPERTY_R, PROPERTY_S, PROPERTY_W, PROPERTY_IGS, осталось бы всего два: PROPERTY_GET и PROPERTY_SET. которые были бы применимы как к членам-данным включая массивы, так и к сетерам/гетерам. |
| Автор: Ivan. 15.9.2011, 20:29 | ||
| я долго пытался решить эту задачу с помощью template, я бы даже сказал, не один год. вот так вот спишь ночью и вдруг приходит сонная мысль - "вот же оно решение!, в теории все должно работать". просыпаешься, начинаешь реализовывать и опять та же самая непреодолимая стена. дело в том, что определение смещения поля от корня класса:
|
| Автор: Ivan. 16.9.2011, 08:33 | ||||||
да вроде бы есть уже:
вот с сочетанием [геттера или сеттера] и прямого обращения - тут немного сложнее. Добавлено через 6 минут и 47 секунд даже я бы сказал, что лучше вот так:
|