Я хочу указатель на член x (и доступ при разименовании к любому элементу), и/или указатель скажем на третий элемент (как указатель на член)
double A::*[10] p = &A::x;
double A::*p = &A::x [3];
че то в этом роде, но оно нефига не собирается (ни то ни то, на уровне синтакиса не так). Я могу конечно в ручную приводить типы и вычислять смещения, но хочется это делать Ъ...
error: invalid use of ‘unary *’ on pointer to member
зачем это нужно. Как там звучит настоящий вопрос?
Так и звучит. У меня есть некая заморочная хитропараметризованная функция, которая принимает через аргумент шаблона указатель на член класса (скажем типа double). Беда в том, что поле на которое передаем указатель может быть не просто полем, но и элементом массива.
Я могу конечно передавать через два аргумента тип поля и смещение от начала структуры, но уж больно это хардкорно (стремно) выглядит... да и работать с этим неудобно.
Ну я поэтому и спрашивал, как звучит настоящий вопрос. ЕМНИП, указатель на член - это смещение от начала объекта, он не имеет смысла без указателя на объект.
Это понятно. Непонятно почему нельзя смещение (число в байтах) кастануть к указателю на член. Можно конечно и со смещением работать, но это довольно уродливо выглядит, типа
Непонятно почему нельзя смещение (число в байтах) кастануть к указателю на член
Потому что оно является смещением от начала только в простых случаях. Когда в дело вступает множественное виртуальное наследование, там уже не смещение, а что-то более сложное. Правда, деталей я не помню.
Ну для POD-типов то оно всегда смещение как смещение?
Для ответа нужно быть действующим Си++-прогером :) Я _думаю_, что для POD и любого не-виртуального наследования это просто смещение. Но как преобразовать его именно в указатель на член, я не знаю %)
Да, для POD-типов оно _всегда_ смещение как смещение. В С++ спецификации даже чёткое определение POD-типов и POD-классов выделено.
Система загрузки данных из БД в память в MaNGOS, например, именно на этом факте построена. Куча строк типа «iiiiiiiccllllillllcccccc» и огромный кусок памяти, который из этих строк распарсивается по i -> int, c - char *, l -> long.
Непонятно почему нельзя смещение (число в байтах) кастануть к указателю на член.
Потому что указатель на член кроме собственно самого смещения относительно начала структуры (класса) содержит еще указатель на сам объект, который передается при вызове функции-члена первым аргументом неявно как this, а при доступе к переменной члену используется как this->member_variable. Само по себе абстрактное смещение без конкретизации объекта бессмыссленно.
O! Я все время забываю про возможности юниона в качестве грязных хаков с кастингом, спасибо!
Поздравляю, ты только что сделал все необходимые приготовления для стрельбы по собственным яйцам! Работоспособность твоего костыля зависит от конкретного компилятора.
Как-то слишком общо. Это реально с программированием связано ? Имхо эти нетривиальные упражнения с членами класса доставляют не по-детски, только непонятно как, чую жизнь мимо проходит.
По такому коду однозначно детектится ООП головного мозга в терминальной стадии.
По такому коду однозначно детектится профессиональный программист, который отличается от хакира-борщевика сакральным знанием того, что на чтение кода уходит на порядок больше времени чем на написание. И каждый вотзефак такого типа стоит много денег.
Необходимость выковыривания смещения члена класса — однозначный признак того, что архитектор — мудак.
Вообще говоря, наприсанное — UB. На практике, начиная с -O2 GCC не постесняется переставить «pu.ptr = (T A::*)ptr;» и «pu.offset += i*sizeof(T);» местами
Теперь подумайте, что делать если известно поле класса, но еще неизвестен экземпляр (его просто нету пока).
По такому коду однозначно детектится профессиональный программист,
Ога, Ога. Меня всегда умиляла эта гордость от принадлежности к касте. Есть нюанс - в наших задачах про. программисты нафик ненужны, от них нет никакого толку. Все чему их учат крайне полезно и помогает при работе в большой команде, и очень мешает при разработке наукоемкого кода в группе из макс. трех человек. Когда приходит студент с задатками проф. программиста заложенными на младших курсах, его приходится долго бить по рукам что бы не писал геттеров/сеттеров, не сносил строку после каждой инструкции и скобки и т.д. Потому что в нашей области свой код читаешь в основном ты сам, гораздо реже такие же мудаки, но никогда проф. программисты. Потому что проф. программисты не знают нихера предметной области, и как бы не был отформатирован код, как бы не был он прекрасен с т.з. какононов проф. программирования, проф программист все равно в нем нихера не поймет. Это не браузеры писать, задачи очень специфические.
Теперь подумайте, что делать если известно поле класса, но еще неизвестен экземпляр (его просто нету пока).
Вы должны мне новый парсер... В общем случае ответ — «шаблоны», но я подозреваю, что ваша проблема намного серьёзнее.
Ога, Ога. Меня всегда умиляла эта гордость от принадлежности к касте.
Это не гордость, а усталые вздохи и потирание синяков от фейспалмов...
его приходится долго бить по рукам что бы не писал геттеров/сеттеров
Доооо. Надо писать (char *)(this) + &(A::x). В действительности, возле большинства геттеров/сеттеров (в частности, возле приведённого мной) надо писать комментарий вида «У меня необратимое поражение той части мозга, которая отвечает за правильную декомпозицию. Но я не настолько упорот чтобы выдёргивать указатели на члены».
Сейчас задумываюсь, что вы путаете требования к кодинг стайлу с требованиями к производительности. Это довольно перпендикулярные вещи. В частности, разница между «double *GetXRef() { return x; }» и вашей конструкцией врядли измерима. А проблемы с dataflow, которые могут давать вполне измеримые значения, налицо.