Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Приведение указателя на функцию-член к void*


Автор: AtroX 22.8.2005, 23:27
Задача написать специализацию (или специализации) функции
Код

template <typename T, typename U> U MakeAnyPtr(T);


Которая позволяет делать так:
Код

struct Some {
   void f();
};

void main()
{
   Some *ps    = new Some;
   void   *p_fn = MakeAnyPtr<void*>(Some::f);

   (ps->*MakeAnyPtr<void (Some::*)()>(p_fn))();
}


Автор: Дрон 22.8.2005, 23:59
AtroX
Хех... Уже писал, но напишу ещё разок. Уж очень меня это прёт smile

Код

template <typename SRC_T, typename DEST_T>
DEST_T MakeAnyPtr(SRC_T inptr)
{
    union 
    {
        SRC_T  _inptr;
        DEST_T _outptr;
    };
    _inptr = inptr;
    return _outptr;
}


http://forum.vingrad.ru/index.php?showtopic=52386&view=findpost&p=413508

Автор: srd 23.8.2005, 04:54
НЕЛЬЗЯ ТАК ДЕЛАТЬ! Кто сказал, что указатель на функцию-член имеет одинаковый размер с обычным указателем? В простейшем случае так и есть, но в случае множественного наследования/виртуальных функций - нет.

Вот пример:
Код

class R
{
};

class R1 : public virtual R
{
};

class R2 : public virtual R
{
};

class A : public R1, public R2
{
public:
    void func( void )
    {
    }
};

template <typename DEST_T, typename SRC_T>    
DEST_T MakeAnyPtr(SRC_T inptr)    
{    
    union    
    {    
        SRC_T  _inptr;    
        DEST_T _outptr;    
    };    
    _inptr = inptr;    
    return _outptr;    
}

int main( void )
{
    void* p = MakeAnyPtr<void*>( A::func );

    // Указатель на функцию член безвозратно потерян, т.к. он не влазит в 4-байта.
    void (A::*pf)(void) = MakeAnyPtr<void (A::*)(void)>( p );

    A a;
    (a.*pf)(); // Программа тут свалится.

    return 0;
}


Автор: AtroX 23.8.2005, 11:05
Цитата(srd @ 23.8.2005, 04:54)
// Указатель на функцию член безвозратно потерян, т.к. он не влазит в 4-байта.

sizeof(void (A::*)(void)) == 12, офигеть!

Цитата
Хех... Уже писал, но напишу ещё разок. Уж очень меня это прёт

Ага, обломчик, нельзя так..
Задачка то не тривиальна smile

Автор: Fantasist 23.8.2005, 12:13
AtroX

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

В STL есть функция mem_fun() которая возвращает объект mem_fun_t, который представляет указетель на метода класса.

Код


#include <functional>

struct Some {
   void f();
};

int main()
{
   Some* p = new Some();
   
   std::mem_fun_t<void,Some> pM(&Some::f);

   pM(p); //p->f(); 
}



Автор: Дрон 23.8.2005, 12:41
Цитата(srd @ 23.8.2005, 05:54)
но в случае множественного наследования/виртуальных функций - нет.

Ибо нефиг. Я, кстати, об этом догадывался
Цитата
Кроме того, с виртуальными функциями такой фокус может быть опасен (хотя я не уверен -- сам не проверял).


А вообще Fantasist правильную вещь говорит smile

Автор: AtroX 23.8.2005, 17:47
Цитата(Fantasist @ 23.8.2005, 12:13)
Ты уверен, что хочешь иметь именно функцию, которая бы приводила бы указатель на метод к указателю void*?

Не надо, без хака все равно не получится.

Придется динамически выделять память под функтор, который будет в себе хранить указатель на мембер.

Цитата(Fantasist @ 23.8.2005, 12:13)
В STL есть функция mem_fun() которая возвращает объект mem_fun_t, который представляет указетель на метода класса.

Там всего 0 или 1 переменная может быть - не катит, проще использовать из boost'а или самому написать.

Автор: Fantasist 23.8.2005, 18:40
Цитата(AtroX @ 23.8.2005, 14:47)
Не надо, без хака все равно не получится.

Придется динамически выделять память под функтор, который будет в себе хранить указатель на мембер.


Не понял ни первого ни второго предложения. smile Чего "не надо", и чего не получится?

Зачем надо динамически выделять память под функтор?


Цитата(AtroX @ 23.8.2005, 14:47)
Там всего 0 или 1 переменная может быть - не катит, проще использовать из boost'а


Можно, конечно, просто в соседней ветке ты написал тоже только для одного/двух параметров фактически переписав STL. А самому писать не стоит - boost вскоре тоже собираются в стандарт включать.

Автор: AtroX 23.8.2005, 20:00
Цитата(Fantasist @ 23.8.2005, 18:40)
Чего "не надо"

Не надо к void* приводить, плохая это идея =))

Цитата(Fantasist @ 23.8.2005, 18:40)
А самому писать не стоит

Иногда стоит, когда не хочешь подключать всю библиотеку(ну или часть).
Цитата(Fantasist @ 23.8.2005, 18:40)
Зачем надо динамически выделять память под функтор?

Чтобы хранить в этом функторе нормальный указатель на мембер, раз я не знаю его размера. Как и сделано в соседней ветке.


Цитата(Fantasist @ 23.8.2005, 18:40)
Можно, конечно, просто в соседней ветке ты написал тоже только для одного/двух параметров фактически переписав STL.

У меня у функторов общий базовый класс, что важно и чего нет в STL.
Для одного и двух пар-ров я сделал только для примера, а вообще реально нужно около 4х.

Автор: Chaos A.D. 24.8.2005, 09:15
Цитата(AtroX @ 23.8.2005, 20:00)
Чтобы хранить в этом функторе нормальный указатель на мембер, раз я не знаю его размера.

Не знаю, подойдет ли тебе это, но функтор можно, и, имхо, нужно передавать по значению. Так же, если нужна общность функторов для разного типа и количества аргументов, и без наследования, советую присмотреться к Loki::Functor

Автор: AtroX 24.8.2005, 16:32
Цитата(Chaos @ 24.8.2005, 09:15)
Не знаю, подойдет ли тебе это, но функтор можно, и, имхо, нужно передавать по значению.


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

Автор: Nastya 24.8.2005, 17:39
http://www.rsdn.ru/article/cpp/fastdelegate.xml

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)