Здравствуйте, night beast, Вы писали:
NB>Недавно столкнулся с такой непонятной штукой.
NB>Указатель на мембер-функцию не является указателем.
Да, это более сложная сущность.
NB>Какие причины такого решения?
Ну хотя бы то, что размеры указателя и указателя на член в общем случае не совпадают.
Здравствуйте, Bell, Вы писали:
NB>>Какие причины такого решения? B>Ну хотя бы то, что размеры указателя и указателя на член в общем случае не совпадают.
Размеры указателей на int и на double тоже "в общем случае" не совпадают.
Здравствуйте, Bell, Вы писали:
NB>>Недавно столкнулся с такой непонятной штукой.
NB>>Указатель на мембер-функцию не является указателем. B>Да, это более сложная сущность.
NB>>Какие причины такого решения? B>Ну хотя бы то, что размеры указателя и указателя на член в общем случае не совпадают.
ну а вот, например, размер указателя и указателя на функцию тоже не обязаны совпадать. однако для указателей на функцию все работает как надо.
Здравствуйте, night beast, Вы писали:
NB>>>Какие причины такого решения? B>>Ну хотя бы то, что размеры указателя и указателя на член в общем случае не совпадают.
NB>ну а вот, например, размер указателя и указателя на функцию тоже не обязаны совпадать. однако для указателей на функцию все работает как надо.
Указатели (на объекты, функции, void) и указатели на нестатические члены класса относятся к разным группам типов, с т.з. стандарта, ничего здесь не поделаешь. Причина этому, наверное, тот факт, что указатели, обычно, представляют собой адрес, тогда как указатели на члены — не совсем.
Здравствуйте, zaufi, Вы писали:
NB>>Недавно столкнулся с такой непонятной штукой.
NB>>Указатель на мембер-функцию не является указателем.
Z>добавь выделенную специализацию... Z>в общем случае нада заспециализироваться для функций с 1,2,3,...,N параметрами...
именно!
приходится плодить кучу специализаций на ровном месте (добавь еще к ним указатель на постоянную мембер функцию)
это нормально по вашему?
Здравствуйте, shank, Вы писали:
S>Указатели (на объекты, функции, void) и указатели на нестатические члены класса относятся к разным группам типов, с т.з. стандарта, ничего здесь не поделаешь. Причина этому, наверное, тот факт, что указатели, обычно, представляют собой адрес, тогда как указатели на члены — не совсем.
дело в том, что указатель на функцию в общем случае не может быть преобразован к указателю на void (что справедливо для обычных объектов).
и в этом плане он не отличается от указателя на мембер.
Здравствуйте, night beast, Вы писали:
Z>>в общем случае нада заспециализироваться для функций с 1,2,3,...,N параметрами...
NB>именно! NB>приходится плодить кучу специализаций на ровном месте (добавь еще к ним указатель на постоянную мембер функцию) NB>это нормально по вашему?
ну а попробуй написать просто is_pointer_to_function, без функций-членов — получишь то же самое.
Хотя, может быть, тут удастся извратиться методом исключения, но не суть.
Здравствуйте, night beast, Вы писали:
NB>дело в том, что указатель на функцию в общем случае не может быть преобразован к указателю на void (что справедливо для обычных объектов).
Кстати такое преобразование, по идее, должно давать ошибку компиляции (даже если используются reinterpret_cast или c-cast).
NB>и в этом плане он не отличается от указателя на мембер.
Я о другом, указатель на функцию является "просто" указателем (pointer), как и указатели на объекты, тогда как указатель на функцию-член — это pointer-to-member, совершенно другая группа типов.
Здравствуйте, jazzer, Вы писали:
Z>>>в общем случае нада заспециализироваться для функций с 1,2,3,...,N параметрами...
NB>>именно! NB>>приходится плодить кучу специализаций на ровном месте (добавь еще к ним указатель на постоянную мембер функцию) NB>>это нормально по вашему?
J>ну а попробуй написать просто is_pointer_to_function, без функций-членов — получишь то же самое. J>Хотя, может быть, тут удастся извратиться методом исключения, но не суть.
да. но вопрос то в другом.
тот код отлично работает для указателей на функцию без специализаций.
вот и интересуюсь, в чем причина.
Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, zaufi, Вы писали:
NB>>>Недавно столкнулся с такой непонятной штукой.
NB>>>Указатель на мембер-функцию не является указателем.
Z>>добавь выделенную специализацию... Z>>в общем случае нада заспециализироваться для функций с 1,2,3,...,N параметрами...
NB>именно! NB>приходится плодить кучу специализаций на ровном месте (добавь еще к ним указатель на постоянную мембер функцию) NB>это нормально по вашему?
если ломно заморачиваться используй boost::type_traits -- не изобретай велосипед... все уже сделано давно до тебя!
--
а вообще такая проблема лекго решается препроцессором генерящим для тебя нужное количество требуемых специализаций
(для чего также удобно использовать BOOST_PP_... макросы
Здравствуйте, shank, Вы писали:
NB>>и в этом плане он не отличается от указателя на мембер. S>Я о другом, указатель на функцию является "просто" указателем (pointer), как и указатели на объекты, тогда как указатель на функцию-член — это pointer-to-member, совершенно другая группа типов.
"просто" указатель -- низкоуровневая абстракция.
вот лично ты видишь логические основания не считать pointer-to-member указателем?
Здравствуйте, night beast, Вы писали:
NB>"просто" указатель -- низкоуровневая абстракция. NB>вот лично ты видишь логические основания не считать pointer-to-member указателем?
При прочтеннии этой ветки пришла такая мысль, почему бы не трактовать функции-члены, как обычные функции, но с дополнительным параметром в начале списка — аналогом this, передающимся неявно.
код мог бы быть таким:
class A{
public: void f(void);
};
A a;
void (*pfn)(A*) = &A::f;
(*pfn)(&a);
Здравствуйте, zaufi, Вы писали:
NB>>именно! NB>>приходится плодить кучу специализаций на ровном месте (добавь еще к ним указатель на постоянную мембер функцию) NB>>это нормально по вашему?
Z>если ломно заморачиваться используй boost::type_traits -- не изобретай велосипед... все уже сделано давно до тебя!
)
это просто одна из иллюстраций проблемы.
вот еще:
template<typename T>
void foo ( T * );
template<typename T>
void foo ( const T & );
foo (&test::bar);
Z>-- Z>а вообще такая проблема лекго решается препроцессором генерящим для тебя нужное количество требуемых специализаций Z>(для чего также удобно использовать BOOST_PP_... макросы
"кто сказал что микроскопом нельзя забивать гвозди? главное колотить сильнее" (с)
Здравствуйте, valker, Вы писали:
V>Здравствуйте, night beast, Вы писали:
NB>>"просто" указатель -- низкоуровневая абстракция. NB>>вот лично ты видишь логические основания не считать pointer-to-member указателем?
V>При прочтеннии этой ветки пришла такая мысль, почему бы не трактовать функции-члены, как обычные функции, но с дополнительным параметром в начале списка — аналогом this, передающимся неявно.
V>код мог бы быть таким:
V>
shank wrote:
> NB>>Какие причины такого решения? > B>Ну хотя бы то, что размеры указателя и указателя на член в общем > случае не совпадают.
Совпадают.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, shank, Вы писали:
S>Здравствуйте, Bell, Вы писали:
NB>>>Какие причины такого решения? B>>Ну хотя бы то, что размеры указателя и указателя на член в общем случае не совпадают.
S>Размеры указателей на int и на double тоже "в общем случае" не совпадают.
Здравствуйте, Bell, Вы писали:
S>>Размеры указателей на int и на double тоже "в общем случае" не совпадают.
B>Неужели?
Угу.
Единственное, что гарантируется касательно размеров указателей, это то, что размер void* достаточен для того, чтобы "вместить" указатель на объект любого типа, а также то что sizeof(void*) == sizeof(char*). Больше никаких гарантий. (Это объяснялось где-то Steve'ом Clamage'ом, если мне склероз не изменяет).
3.9.2/4
Objects of cv-qualified (3.9.3) or cv-unqualified type void* (pointer to void), can be used to point to
objects of unknown type. A void* shall be able to hold any object pointer. A cv-qualified or cv-
unqualified (3.9.3) void* shall have the same representation and alignment requirements as a cv-qualified
or cv-unqualified char*.
Здравствуйте, valker, Вы писали:
V>При прочтеннии этой ветки пришла такая мысль, почему бы не трактовать функции-члены, как обычные функции, но с дополнительным параметром в начале списка — аналогом this, передающимся неявно.
Такой метод использовал Страуструп во времена, когда в C++ еще не было указателей на члены, а они ему были нужны. Потом он ушел от этого, определив в языке такой тип как "указатель на член", тем самым сделав систему типов более логичной. Подробнее см. "Дизайн и эволюция C++".
Re[7]: указатель на мембер
От:
Аноним
Дата:
11.08.06 15:43
Оценка:
Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, shank, Вы писали:
NB>>>и в этом плане он не отличается от указателя на мембер. S>>Я о другом, указатель на функцию является "просто" указателем (pointer), как и указатели на объекты, тогда как указатель на функцию-член — это pointer-to-member, совершенно другая группа типов.
NB>"просто" указатель -- низкоуровневая абстракция. NB>вот лично ты видишь логические основания не считать pointer-to-member указателем?
Скажем так:
"просто указатель" — это смещение в некотором хранилище, по которому находится некоторый объект.
pointer-to-member — это смещение члена от смещения в некотором хранилище, по которому находится некоторый объект.
Код ф-ии члена хранится только в одном месте, делая похожей ф-ию-член на обычную. Следовательно можно было бы использовать "просто указатель" на ф-ию-член. Однако это абсолютно не работает по отношению к членам-данным (см.определения выше). Поэтому создали универсальную сущность pointer-to-member...
Личное мнение — неудобств это не вызывает, а четко отделенное понятие упрощает понимание.
Здравствуйте, Аноним, Вы писали:
А>Код ф-ии члена хранится только в одном месте, делая похожей ф-ию-член на обычную. Следовательно можно было бы использовать "просто указатель" на ф-ию-член. Однако это абсолютно не работает по отношению к членам-данным (см.определения выше). Поэтому создали универсальную сущность pointer-to-member...
Я не против того что это отдельная сущьность. Мне не удобно что у этой сущьности поведение отличается от поведения
похожих сущьностей.
А>Личное мнение — неудобств это не вызывает, а четко отделенное понятие упрощает понимание.
Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, shank, Вы писали:
S>>Указатели (на объекты, функции, void) и указатели на нестатические члены класса относятся к разным группам типов, с т.з. стандарта, ничего здесь не поделаешь. Причина этому, наверное, тот факт, что указатели, обычно, представляют собой адрес, тогда как указатели на члены — не совсем.
NB>дело в том, что указатель на функцию в общем случае не может быть преобразован к указателю на void (что справедливо для обычных объектов). NB>и в этом плане он не отличается от указателя на мембер.
Гляньте пример в Detours.
//////////////////////////////////////////////////////////////////////////////
//
// Test a detour of a member function (member.cpp of member.exe)
//
// Microsoft Research Detours Package, Version 2.1.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// By default, C++ member functions use the __thiscall calling convention.
// In order to Detour a member function, both the trampoline and the detour
// must have exactly the same calling convention as the target function.
// Unfortunately, the VC compiler does not support a __thiscall, so the only
// way to create legal detour and trampoline functions is by making them
// class members of a "detour" class.
//
// In addition, C++ does not support converting a pointer to a member
// function to an arbitrary pointer. To get a raw pointer, the address of
// the member function must be moved into a temporrary member-function
// pointer, then passed by taking it's address, then de-referencing it.
// Fortunately, the compiler will optimize the code to remove the extra
// pointer operations.
//
// If X::Target is a virtual function, the following code will *NOT* work
// because &X::Target is the address of a thunk that does a virtual call,
// not the real address of the X::Target. You can get the real address
// of X::Target by looking directly in the VTBL for class X, but there
// is no legal way to 1) get the address of X's VTBL or 2) get the offset
// of ::Target within that VTBL. You can of course, figure these out for
// a particular class and function, but there is no general way to do so.
Здравствуйте, Аноним, Вы писали:
А>Код ф-ии члена хранится только в одном месте, делая похожей ф-ию-член на обычную. Следовательно можно было бы использовать "просто указатель" на ф-ию-член.
Нельзя, чтоб позвать функцию-член нужно иметь this, а this-ы бывают разные при множественном наследовании ЕМНИП где-то преобразования this делают специальные прокладки в пару команд, так что и код в одном месте не хранится.
Re[2]: указатель на мембер
От:
Аноним
Дата:
06.08.09 14:03
Оценка:
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, night beast, Вы писали:
NB>>Недавно столкнулся с такой непонятной штукой.
NB>>Указатель на мембер-функцию не является указателем. B>Да, это более сложная сущность.
NB>>Какие причины такого решения? B>Ну хотя бы то, что размеры указателя и указателя на член в общем случае не совпадают.
Cам разок на это натыкался и выяснил, что в .Net ++'ом компиляторе размеры совпадают, а в gcc (на тот момент под рукой был 2.9.x) нет.
2-варианты, либо реализация зависит от компилятора, либо один из них не"до"поддерживает стандарт, по части указателей на мембер классы
Здравствуйте, night beast, Вы писали:
NB>Недавно столкнулся с такой непонятной штукой. NB>Указатель на мембер-функцию не является указателем. NB>Какие причины такого решения?
Он им и не является. Когда мы говорим "указатель на функцию", мы имеем в виду нечто сложное, учитывающее сигнатуру конкретной функции. Когда мы говорим просто "указатель", мы мгновенно получаем кучу бенефитов: дуализм с массивами, создание по указателю, адресную арифметику... всего этого мы лишаемся при "указателе на функцию". Именно поэтому специализация к T* считает, что вам нужно нечто, что является честным указателем со всей его обвязкой, чем указатель на функцию на является. Попробуйте например на вкус вот такой код:
template<typename T>
struct is_pointer<T*> {
int test_pointer_properties(T* arg){
T* next = arg++;
next += 10;
T* newobj = new T();
delete newobj;
T someobj = arg[0];
arg = &someobj;
return 0;
}
};
Здравствуйте, Tilir, Вы писали:
T>Как вы там представляете указатель на функцию?
на обычную функцию указатель приводим к (void *) и обратно. Он указатель, просто сам обьект не копируем и не имеет характеристики длинны. А дуализм массив-указатель ИМХО не всегда нужен, нужен дополнительный тип мутабельная_ссылка, чтоб к типу с адресной арифметикой в явную приводилась.
Здравствуйте, shank, Вы писали:
S>>>Размеры указателей на int и на double тоже "в общем случае" не совпадают.
B>>Неужели?
S>Угу. S>Единственное, что гарантируется касательно размеров указателей, это то, что размер void* достаточен для того, чтобы "вместить" указатель на объект любого типа, а также то что sizeof(void*) == sizeof(char*). Больше никаких гарантий. (Это объяснялось где-то Steve'ом Clamage'ом, если мне склероз не изменяет).
Чисто гипотетически, это может пригодиться для машин со слишком широким словом данных (БЭСМ-6, IBM-360, какие-нибудь современные DSP). Одно слово — один double.
Машинный адрес — только пословно. Чтобы адресоваться посимвольно, нужно тащить ещё и сдвиг символа в слове.
Тогда указатели на числа и на выравненные структуры данных — это адреса, а указатели на символы — это уже пара (адрес,сдвиг).
Можно, конечно, пойти паскалевской дорогой, ввести тип упакованной строки... Типа, диалект для экзотической платформы.
Чуть-чуть пендатизма.
S>...а также то что sizeof(void*) == sizeof(char*). ...
В приведенной строчке надо либо убрать один знак =, либо видоизменить ее так:
(sizeof(void*) == sizeof(char*)) = true
Здравствуйте, Programador, Вы писали:
P>на обычную функцию указатель приводим к (void *) и обратно. Он указатель, просто сам обьект не копируем и не имеет характеристики длинны. А дуализм массив-указатель ИМХО не всегда нужен, нужен дополнительный тип мутабельная_ссылка, чтоб к типу с адресной арифметикой в явную приводилась.
Пока такого типа нет (и вряд ли будет), программист, особенно с опытом на C, волен ожидать от специализированного на "указатель" типа всё, что традиционно можно вытворять с указателем. Включая и то, что вам лично кажется не нужным