Re[7]: указатель на под-член
От: Erop Россия  
Дата: 18.12.09 07:38
Оценка: 1 (1)
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Тем более, что твоя superposition будет, конечно, вынесена в хедер, а хедеры никто не смотрит.

Выделенный тезис представляется мне более чем сомнительным...

PD>В итоге... если что-то потом окажется не так, придется разбираться намного дольше. У меня же все ясно и недвусмысленно сказано.


Фишка вы том, что
1) в superposition можно организовать, вообще-то контроль типов.
2) можно организовать тестирование работоспособности этого хака, чтобы на платформе, где всё сломается, сразу и не собралось бы или не запустилось и т. д.
3) (на самом деле главное), когда понадобится переносить этот код на платформу, где хак будет немного другой (например, будут хранить в указателе на поле не смещение, а смещение + константа), то в варианте с superposition понадобится сделать условную компиляцию в одном месте, а у тебя всюду в клиентском коде. И объём правок, конечно разный.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: указатель на под-член
От: Pavel Dvorkin Россия  
Дата: 18.12.09 07:52
Оценка:
Здравствуйте, Erop, Вы писали:

PD>>Тем более, что твоя superposition будет, конечно, вынесена в хедер, а хедеры никто не смотрит.

E>Выделенный тезис представляется мне более чем сомнительным...

Когда ты последний раз заглядывал в stdio.h ?

PD>>В итоге... если что-то потом окажется не так, придется разбираться намного дольше. У меня же все ясно и недвусмысленно сказано.


E>Фишка вы том, что

E>1) в superposition можно организовать, вообще-то контроль типов.
E>2) можно организовать тестирование работоспособности этого хака, чтобы на платформе, где всё сломается, сразу и не собралось бы или не запустилось и т. д.
E>3) (на самом деле главное), когда понадобится переносить этот код на платформу, где хак будет немного другой (например, будут хранить в указателе на поле не смещение, а смещение + константа), то в варианте с superposition понадобится сделать условную компиляцию в одном месте, а у тебя всюду в клиентском коде. И объём правок, конечно разный.

В общем, со многим можно согласиться, но лучше вообще это нигде не писать и не провоцировать, делая вид, что superposition — это честная функция, а не злобный хак
With best regards
Pavel Dvorkin
Re[9]: указатель на под-член
От: Erop Россия  
Дата: 18.12.09 08:09
Оценка: 1 (1)
Здравствуйте, Pavel Dvorkin, Вы писали:


PD>Когда ты последний раз заглядывал в stdio.h ?

Ну он, во-первых, стандартный, и, во-вторых, я им вроде бы не пользуюсь к тому же...

PD>>>В итоге... если что-то потом окажется не так, придется разбираться намного дольше. У меня же все ясно и недвусмысленно сказано.


Если написать superposition достаточно аккуратно, то сразу будет понятно где разбираться...

PD>В общем, со многим можно согласиться, но лучше вообще это нигде не писать и не провоцировать, делая вид, что superposition — это честная функция, а не злобный хак


Ну так ясно, что без хака лучше
Но мы сравнивали не вариант с хаком и вариант без, а твой с superposition...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: указатель на под-член
От: rg45 СССР  
Дата: 18.12.09 11:20
Оценка:
Здравствуйте, tyomitch, Вы писали:

T>Коллеги, возник ещё один вопрос по теме.

T>Как сделать указатель на "невидимый член" базового класса?
T>К примеру:

T>
T>struct A { float w; int x; } ;
T>struct B { char y; } ;
T>struct C : public A, public B { } ;
T>B C::* p;
T>C c;
T>


T>И цель — чтобы c.*p было эквивалентно (B)c


T>Опять же, кажется, что можно изхитриться и узнать смещение предка в потомке, а по нему сконструировать указатель?


Ну и я отмечусь:
template<typename Base, typename Derived>
Base Derived::* reinterpret_base_as_member()
{
  int derived_ = 123; //Что угодно, но не 0!
  Derived* derived = reinterpret_cast<Derived*&>(derived_);
  Base* base = derived;
  int base_ = reinterpret_cast<int&>(base);
  int offset = base_ - derived_;
  Base Derived::* member = reinterpret_cast<Base Derived::*&>(offset);
  return member;
}


Использовать так:

#include <iostream>

struct A { int a; };
struct B { int b; };
struct AB : A, B { };

B AB::* m = reinterpret_base_as_member<B, AB>();

int main()
{
  AB t;
  (t.*m).b = 123;
  
  std::cout << t.b << std::endl; //Output: 123
}


Хочется обратить внимание на присутствие контроля типов. Если попытаться вызвать reinterpret_base_as_member для типов, не являющихся предком и потомком, то будет ошибка компиляции. Также контроль типов присутствует и здесь
Автор: rg45
Дата: 13.12.09
.
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: указатель на под-член
От: Кодт Россия  
Дата: 18.12.09 15:41
Оценка: 7 (1)
Здравствуйте, rg45, Вы писали:

R>Для начала определим обобщенную функцию, которая по двум указателям — на член и на подчлен — возвращает их "суперпозицию", так сказать:


Извините, что влезаю в дискуссию... А что, если с самого начала избавиться от такого явления, как указатель на член?

Указатель на член — это особая функция, на вход которой подают ссылку на объект, а на выходе — ссылка на другой объект.
Сделаем из него не особую, а обычную функцию.
template<class Host, class Member, Member Host::*mp>
Member& member(Host& host) { return host.*mp; }

// суперпозиция во время компиляции
template<class A, class B, class C, B&(*a2b)(A&), C&(*b2c)(B&)>
C& superposition(A& a) { return b2c(a2b(a)); }

struct P { int x, y; };
struct Q { P z; int t; };

int& (*get_t)(Q&) = member<Q,int,&Q::t>;
int& (*get_x)(Q&) = superposition<Q,P,int, member<Q,P,&Q::z>, member<P,int,&P::x> >;

Q q = { { 1, 2 }, 3 };

int& t = get_t(q);
int& x = get_x(q);


Здесь получилось нечто многословное, с явным указанием типов всех участников.
Можно подумать, как допилить до автоматического вывода. Возможно, завернуть в шаблоны классов...


И кстати, указатели на члены-данные прекрасно замыкаются в boost::bind / boost::function.
Понятно, что оверхед и всё такое, но может, у компилятора хватит ума проинлайнить — чтобы bind(&P::x, bind(&Q::z, _1))(q) превратилось в q.*(&Q::z).*(&P::x) — а оттуда в q.z.x ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[5]: указатель на под-член
От: rg45 СССР  
Дата: 18.12.09 16:32
Оценка:
Здравствуйте, Кодт, Вы писали:

К>
К>// суперпозиция во время компиляции
К>template<class A, class B, class C, B&(*a2b)(A&), C&(*b2c)(B&)>
К>C& superposition(A& a) { return b2c(a2b(a)); }

К>int& (*get_x)(Q&) = superposition<Q,P,int, member<Q,P,&Q::z>, member<P,int,&P::x> >;
К>


Да, в этом месте очень не хватает автоматического выведения пареметров шаблонной функции по параметрам же шаблона. Наподобие того, как параметры шаблона выводятся из параметров функции.

Казалось бы, чего бы не перенести указатели на функции из списка параметров шаблона в список параметров функции? А тут есть один тонкий момент, который не всеми сходу улавливается. А между тем, разница в возможностях использования указателей на функции, находящихся в списке параметров шаблона, и указателей в списке параметров функции огромная. Пока указатель на функцию находится в параметрах шаблона он является константой времени компиляции, и на его основе можно определить другую функцию и получить указатель другого типа, и тоже во время компиляции! Таким образом, получается эдакий механизм конвертации указателей на функции. При переносе указателя на функцию из параметров шаблона в параметры функции эта замечательная возможность теряется.

Лет пять назад я делал приспособление, которое долгое время было предметом моей гордости. Оно позволяло перенести-таки указатели на функции из параметров шаблона в параметры функции, и при этом не потерять описанные выше преимущества! При этом вызовы функций, подобных superposition обходились без этих огромных списков шаблонных параметров и стали выглядеть гораздо компактнее, а самое главное, перестали быть чувствительны к изменениям в сигнатурах целевых функций! В основе решения лежал грязнейший хак, гораздо более грязный, чем все вместе взятые, мелькавшие в этой ветке. В двух словах — из сегмента кода вырезались кусочки исполняемого кода и переносились в буфер, расположенный в динамической памяти. Потом еще выполнялась кое-какая дополнительная инициализация этих блочков. После этого этим кусочкам кода в нужный момент передавалось управление. Собственно, эти кусочки и выполняли роль тех самых функций, которые в первом случае можно было генерить совершенно штатным образом. Решение (на MSVC-7.1) было непереносимым, заточенным под 32-битную платформу. Но оно работало и на тот момент все остались чрезвычайно довольны
--
Справедливость выше закона. А человечность выше справедливости.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.