Convert non-static member function pointer to function pointer
От: Nikita.Trophimov  
Дата: 02.04.13 15:24
Оценка: -1
Приветствую.

Есть функция некоторого API, которая принимает в качестве аргумента указатель на свободную функцию. Ей необходимо передать нестатическую функцию-член.

Т.к. напрямую этого сделать нельзя (как известно, указатель на нестатическую функцию-член и указатель на свободную функцию — это абсолютно разные типы), я решил попробовать создать на основе возвращаемого функцией std::bind значения объект класса std::function, у которого вызвать функцию-член target.

http://liveworkspace.org/code/4fZu2N$0

В подобных случаях target возвращает nullptr. Это обсуждалось, например, в рассылке boost'а:

http://lists.boost.org/Archives/boost/2008/12/145709.php

Существует ли вообще нормальный способ преобразовать указатель на функцию-член в указатель на свободную функцию или нет? Предполагаю, что нет, но мало ли кто-нибудь придумал решение.
Re: Convert non-static member function pointer to function pointer
От: uzhas Ниоткуда  
Дата: 02.04.13 15:33
Оценка:
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Существует ли вообще нормальный способ преобразовать указатель на функцию-член в указатель на свободную функцию или нет? Предполагаю, что нет, но мало ли кто-нибудь придумал решение.


концептуально функция член ничего не умеет делать, если ей не передать this, поэтому предположу, что все же хочется сделать замыкание
эта проблема обсуждалась здесь: http://rsdn.ru/forum/cpp.applied/5114972.flat
Автор: vasvladal
Дата: 27.03.13
Re: Convert non-static member function pointer to function pointer
От: Evgeny.Panasyuk Россия  
Дата: 02.04.13 15:34
Оценка:
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Есть функция некоторого API, которая принимает в качестве аргумента указатель на свободную функцию. Ей необходимо передать нестатическую функцию-член.


"this" ты откуда брать собрался?
Если this передаётся как аргумент этой "свободной" функции — то можно сделать простейший враппер:
Result wrap(Foo *foo,int arg)
{
    return foo->method(arg);
}

Если же откуда-то из глобальной области тогда вот это:
live demo
#include <boost/optional.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <ostream>
using namespace std;

template<unsigned ID,typename Functor>
boost::optional<Functor> &get_local()
{
    static boost::optional<Functor> local;
    return local;
}

template<unsigned ID,typename Functor>
typename Functor::result_type wrapper()
{
    return get_local<ID,Functor>().get()();
}

template<typename ReturnType>
struct Func
{
    typedef ReturnType (*type)();
};

template<unsigned ID,typename Functor>
typename Func<typename Functor::result_type>::type get_wrapper(Functor f)
{
    (get_local<ID,Functor>()) = f;
    return wrapper<ID,Functor>;
}

// ----------------------------------------------------------------------

void test(void (*fptr)())
{
    fptr();
}

struct SomeStruct
{
    int data;
    void some_method()
    {
        cout << data << endl;
    }
    void another_method()
    {
        cout << -data << endl;
    }
};

int main()
{
    SomeStruct local[] = { {11}, {22}, {33} };

    test(get_wrapper<0>(  boost::bind(&SomeStruct::some_method,local[0]) ));
    test(get_wrapper<1>(  boost::bind(&SomeStruct::another_method,local[0]) ));

    test(get_wrapper<2>(  boost::bind(&SomeStruct::some_method,local[1]) ));
    test(get_wrapper<3>(  boost::bind(&SomeStruct::another_method,local[1]) ));

    test(get_wrapper<4>(  boost::bind(&SomeStruct::some_method,local[2]) ));
    test(get_wrapper<5>(  boost::bind(&SomeStruct::another_method,local[2]) ));
}
Re: Convert non-static member function pointer to function pointer
От: rg45 СССР  
Дата: 02.04.13 15:41
Оценка: +5
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Есть функция некоторого API, которая принимает в качестве аргумента указатель на свободную функцию. Ей необходимо передать нестатическую функцию-член.

NT>...
NT>Существует ли вообще нормальный способ преобразовать указатель на функцию-член в указатель на свободную функцию или нет? Предполагаю, что нет, но мало ли кто-нибудь придумал решение.

В таких случаях хорошо, если в этом API предусмотрено передача в callback указателя на произвольный пользовательский контекст. В этом случае не сложно написать свою функцию-адаптер вокруг чего угодно и передать ее в качестве callback-а. Если же такой возможности не предусмотрено, то НОРМАЛЬНОГО способа использовать в качестве callback-ов функции члены и функциональные объекты не существует, извращений — сколько угодно. И остается только сказать "спасибо" за заботу разработчикам API.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Convert non-static member function pointer to function pointer
От: niXman Ниоткуда https://github.com/niXman
Дата: 03.04.13 03:28
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>live demo

LWS был снова недоступен?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: Convert non-static member function pointer to function pointer
От: saf_e  
Дата: 03.04.13 07:52
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, Nikita.Trophimov, Вы писали:


NT>>Есть функция некоторого API, которая принимает в качестве аргумента указатель на свободную функцию. Ей необходимо передать нестатическую функцию-член.


EP>"this" ты откуда брать собрался?

EP>Если this передаётся как аргумент этой "свободной" функции — то можно сделать простейший враппер:
EP>
EP>Result wrap(Foo *foo,int arg)
EP>{
EP>    return foo->method(arg);
EP>}
EP>

EP>Если же откуда-то из глобальной области тогда вот это:
EP>live demo
EP>
EP>


В таких случаях можно использовать __COUNTER__, а чтобы не было коллизий при линковке, заворачивать в анонимный неймспейс.
Re[3]: Convert non-static member function pointer to function pointer
От: Evgeny.Panasyuk Россия  
Дата: 03.04.13 10:30
Оценка:
Здравствуйте, niXman, Вы писали:

EP>>live demo

X>LWS был снова недоступен?

Я этот код добавил давно. По ссылке:

148 days 14 hours ago

По поводу LWS (в продолжение темы из другого топика):
1. Я понял почему у меня "www." было — это firefox сам добавлял. В итоге добавил закладку на панель, а то набираешь код, отправляешь — а он вылетает в трубу (потому "что www.")
2. Проверил совсем старые коды — да, они доступны. Но почему-то мне запомнилось, что был период когда они были недоступны.
3. Я зарегистрировался пару недель назад на LWS, а письмо до сих пор не пришло.
Re[3]: Convert non-static member function pointer to function pointer
От: Evgeny.Panasyuk Россия  
Дата: 03.04.13 10:36
Оценка:
Здравствуйте, saf_e, Вы писали:

_>В таких случаях можно использовать __COUNTER__, а чтобы не было коллизий при линковке, заворачивать в анонимный неймспейс.


Можно, но:
1. Это придётся весь вызов заворачивать в макрос (конечно не обязательно)
2. Пропадёт возможность реиспользования слота (может быть существенно, если объекты большие)
3. имхо, для примера — лучше явно показать что происходит, чтобы были видны грабли по поводу коллизий
Re[4]: Convert non-static member function pointer to function pointer
От: saf_e  
Дата: 03.04.13 10:44
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, saf_e, Вы писали:


_>>В таких случаях можно использовать __COUNTER__, а чтобы не было коллизий при линковке, заворачивать в анонимный неймспейс.


EP>Можно, но:

EP>1. Это придётся весь вызов заворачивать в макрос (конечно не обязательно)
EP>2. Пропадёт возможность реиспользования слота (может быть существенно, если объекты большие)
EP>3. имхо, для примера — лучше явно показать что происходит, чтобы были видны грабли по поводу коллизий

Как мне что-то подсказывает самый частый юз-кейс как раз использование уникальный слотов.

Просто я упомянул про способ облегчить себе жизнь (особенно если по файлу беспорядочно раскиданы выделения слотов). Ну а про коллизию имело смысл упомянуть, она не очевидна, а сайд-эффект весьма интересен
Re[5]: Convert non-static member function pointer to function pointer
От: Evgeny.Panasyuk Россия  
Дата: 03.04.13 11:11
Оценка:
Здравствуйте, saf_e, Вы писали:

_>Как мне что-то подсказывает самый частый юз-кейс как раз использование уникальный слотов.

_>Просто я упомянул про способ облегчить себе жизнь (особенно если по файлу беспорядочно раскиданы выделения слотов).

Ничего против счётчика не имею. Во время написания ответа даже подумал об шаблонном счётчике
Автор: remark
Дата: 06.02.07
(без макросов, основанный на implementation specific extensions/bugs).

_>Ну а про коллизию имело смысл упомянуть, она не очевидна, а сайд-эффект весьма интересен


Кстати, другой подход:
1. аллоцировать пул функций при старте (например с помощью boost::mpl::for_each)
2. get_wrapper всегда будет возвращать следующую функцию из пула. если больше нет — то termintate или exception.
Re[6]: Convert non-static member function pointer to function pointer
От: saf_e  
Дата: 03.04.13 11:21
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, saf_e, Вы писали:


_>>Как мне что-то подсказывает самый частый юз-кейс как раз использование уникальный слотов.

_>>Просто я упомянул про способ облегчить себе жизнь (особенно если по файлу беспорядочно раскиданы выделения слотов).

EP>Ничего против счётчика не имею. Во время написания ответа даже подумал об шаблонном счётчике
Автор: remark
Дата: 06.02.07
(без макросов, основанный на implementation specific extensions/bugs).


Спасибо, любопытно, при попытке разобраться в тимплейтах мозг закипает

_>>Ну а про коллизию имело смысл упомянуть, она не очевидна, а сайд-эффект весьма интересен


EP>Кстати, другой подход:

EP>1. аллоцировать пул функций при старте (например с помощью boost::mpl::for_each)
EP>2. get_wrapper всегда будет возвращать следующую функцию из пула. если больше нет — то termintate или exception.

Сомнительное удовольствие
Re[4]: Convert non-static member function pointer to function pointer
От: niXman Ниоткуда https://github.com/niXman
Дата: 03.04.13 11:24
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Я этот код добавил давно. По ссылке:

EP>

EP>148 days 14 hours ago

да, я не обратил внимания.

EP>1. Я понял почему у меня "www." было — это firefox сам добавлял. В итоге добавил закладку на панель, а то набираешь код, отправляешь — а он вылетает в трубу (потому "что www.")

жесть %)
погуглю, что можно сделать с этим... возможно, в htaccess или в конфиге апатча что-то можно подкрутить...

EP>2. Проверил совсем старые коды — да, они доступны. Но почему-то мне запомнилось, что был период когда они были недоступны.

после запуска новой версии, был период, пока я перенес коды с прежней версии сервиса.

EP>3. Я зарегистрировался пару недель назад на LWS, а письмо до сих пор не пришло.

если гуглопочта, то она почему-то(при том, не всегда) кидает письмо активации в спам. хотя, адрес отправителя никогда ранее не использовался. я на нескольких форумах спрашивал, от чего такое может происходить. ничего вразумительного в ответ.
если письмо в спаме таки найдешь — срок его валидности все равно истек. в этом случае, напиши мне в ЛС и сообщи ник+почту, я активирую.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: Convert non-static member function pointer to function pointer
От: carpenter Голландия  
Дата: 03.04.13 13:07
Оценка:
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Существует ли вообще нормальный способ преобразовать указатель на функцию-член в указатель на свободную функцию или нет? Предполагаю, что нет, но мало ли кто-нибудь придумал решение.


ага — static
Весь мир — Кремль, а люди в нем — агенты
Re[5]: Convert non-static member function pointer to function pointer
От: Evgeny.Panasyuk Россия  
Дата: 03.04.13 14:57
Оценка:
Здравствуйте, niXman, Вы писали:

EP>>1. Я понял почему у меня "www." было — это firefox сам добавлял. В итоге добавил закладку на панель, а то набираешь код, отправляешь — а он вылетает в трубу (потому "что www.")

X>жесть %)

вот я ввожу live, он дополняет до liveworkspace.org/ , нажимаю Enter и ссылка превращается в http://www.liveworkspace.org/
Если убрать "выделение автодополнения" либо ввести полностью http://liveworkspace.org — то без www.

X>погуглю, что можно сделать с этим... возможно, в htaccess или в конфиге апатча что-то можно подкрутить...


да, можно попробовать поставить редирект у www

EP>>3. Я зарегистрировался пару недель назад на LWS, а письмо до сих пор не пришло.

X>если гуглопочта, то она почему-то(при том, не всегда) кидает письмо активации в спам. хотя, адрес отправителя никогда ранее не использовался. я на нескольких форумах спрашивал, от чего такое может происходить. ничего вразумительного в ответ.
X>если письмо в спаме таки найдешь — срок его валидности все равно истек. в этом случае, напиши мне в ЛС и сообщи ник+почту, я активирую.

Да, именно в спаме и было, причём только в веб-интерфейсе (а я thunderbird использую). Надо настроить отдачу спама в imap/pop3 — а то вдруг что важное.
Письмо пришло 13 дней назад — только что активировал, всё ОК.

P.S. Кстати, в спаме ещё было нигерийское письмо
Re[6]: Convert non-static member function pointer to function pointer
От: niXman Ниоткуда https://github.com/niXman
Дата: 03.04.13 17:00
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Письмо пришло 13 дней назад — только что активировал, всё ОК.

кстати да, после того как я начал получать сообщения о том, что письма попадают в спам, я убрал срок валидности активации.

EP>P.S. Кстати, в спаме ещё было нигерийское письмо

=)
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[5]: Convert non-static member function pointer to function pointer
От: Erop Россия  
Дата: 03.04.13 18:45
Оценка:
Здравствуйте, saf_e, Вы писали:

_>Просто я упомянул про способ облегчить себе жизнь (особенно если по файлу беспорядочно раскиданы выделения слотов). Ну а про коллизию имело смысл упомянуть, она не очевидна, а сайд-эффект весьма интересен


Таки надёжнее сделать пул с нормальной аллокацией/деаллокацией...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Convert non-static member function pointer to function pointer
От: niXman Ниоткуда https://github.com/niXman
Дата: 04.04.13 13:05
Оценка: 14 (1)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>да, можно попробовать поставить редирект у www

сделал. даже работает =)
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: Convert non-static member function pointer to function pointer
От: uzhas Ниоткуда  
Дата: 05.04.13 07:55
Оценка: 7 (1)
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Существует ли вообще нормальный способ преобразовать указатель на функцию-член в указатель на свободную функцию или нет? Предполагаю, что нет, но мало ли кто-нибудь придумал решение.


кстати, уже есть предложение в стандарт:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3574.html
Re[6]: Convert non-static member function pointer to function pointer
От: saf_e  
Дата: 05.04.13 10:35
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, saf_e, Вы писали:


_>>Как мне что-то подсказывает самый частый юз-кейс как раз использование уникальный слотов.

_>>Просто я упомянул про способ облегчить себе жизнь (особенно если по файлу беспорядочно раскиданы выделения слотов).

EP>Ничего против счётчика не имею. Во время написания ответа даже подумал об шаблонном счётчике
Автор: remark
Дата: 06.02.07
(без макросов, основанный на implementation specific extensions/bugs).


_>>Ну а про коллизию имело смысл упомянуть, она не очевидна, а сайд-эффект весьма интересен


EP>Кстати, другой подход:

EP>1. аллоцировать пул функций при старте (например с помощью boost::mpl::for_each)
EP>2. get_wrapper всегда будет возвращать следующую функцию из пула. если больше нет — то termintate или exception.

Кстати, gcc избавился от заблуждений (http://liveworkspace.org/code/SMLMz$1)
А вот студия вплоть до 2012 верна себе.

Хороший пример того, почему не стоит использовать UB.
Re[2]: Convert non-static member function pointer to function pointer
От: saf_e  
Дата: 05.04.13 10:36
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, Nikita.Trophimov, Вы писали:


NT>>Существует ли вообще нормальный способ преобразовать указатель на функцию-член в указатель на свободную функцию или нет? Предполагаю, что нет, но мало ли кто-нибудь придумал решение.


U>кстати, уже есть предложение в стандарт:

U>http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3574.html

Если примут в С++ появится еще немного черной магии
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.