Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> (g++)указатель на шаблонную функцию 
V
    Опции темы
Леопольд
Дата 27.11.2010, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Код
typedef void(*callback_t)(void*);
void function_with_callback(callback_t callback, void* param)
{
    callback(param);
}

template<class T>
void method_to_fn(void* that)
{
    static_cast<T*>(that)->bar();
}

#include <iostream>
struct Bar
{
   int field;  
} inst;

struct Foo
{
   int field; 
    void bar() { std::cout << "test OK\n"; field = 1234; }
};

int main()
{
    function_with_callback(method_to_fn<Foo>, &inst);
    std::cout << inst.field <<std::endl;
    
    return 0;
}
Ни одного ворнинга.
http://liveworkspace.org/code/bf8a2fa6241c...c42f3af3acb7ab2

Это сообщение отредактировал(а) Леопольд - 27.11.2010, 16:45


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
GoldFinch
Дата 27.11.2010, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 15
Всего: 26



Леопольд, помоему я написал тожесамое

Добавлено через 7 минут и 57 секунд
Всем спасибо за участие, вопрос решен.


---------

собственно ради чего это всё затевалось:
Код

//------- Third-party library code ------

typedef void(*callback_t)(void*);
void function_with_callback(callback_t callback, void* param)
{
    callback(param);
}

//------- Our library code --------

template<class T, void (T::*m)()>
void method_to_fn(void* that)
{
    (static_cast<T*>(that)->*m)();
}

//------- test ------

#include <iostream>

int main()
{
    struct Foo
    {
        void bar() { std::cout << "Foo::bar OK\n"; }
    };

    Foo foo;
    
    function_with_callback(method_to_fn<Foo, &Foo::bar>, &foo);
}


PM MAIL ICQ   Вверх
mes
Дата 27.11.2010, 19:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(GoldFinch @  27.11.2010,  15:47 Найти цитируемый пост)
собственно ради чего это всё затевалось:

угу.. нажить проблемы :
http://liveworkspace.org/code/5b05551a3ef0...3e10f277664cf41



--------------------
PM MAIL WWW   Вверх
Леопольд
Дата 27.11.2010, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(GoldFinch @  27.11.2010,  16:47 Найти цитируемый пост)
Леопольд, помоему я написал тожесамое
Не совсем, я показал что не так с static_cast ( mes показал тоже самое). Можно легко получить UB, компилятор ничем не сможет помочь.
вот ещё UB, компилятор проглотил не поперхнувшись
Код
//------- Third-party library code ------
typedef void(*callback_t)(void*);
void function_with_callback(callback_t callback, void* param)
{
    callback(param);
}
//------- Our library code --------
template<class T, void (T::*m)()>
void method_to_fn(void* that)
{
    (static_cast<T*>(that)->*m)();
}
//------- test ------

#include <iostream>

int main()
{
    struct Foo
    {
        int i;
        void bar() { std::cout << "Foo::bar OK\n"; reinterpret_cast<std::string&>(i) = "Foo1::bar FALSE\n"; }
    };

    struct Foo1
    {
        std::string s;
        void bar(void) { std::cout << s; }
        Foo1() : s("Foo1::bar OK\n") {}
    };

    Foo1 foo;
    
    function_with_callback(method_to_fn<Foo, &Foo::bar>, &foo);

    foo.bar();
}
http://liveworkspace.org/code/43f2050c7444c9c80504d1240d20c1f3

Надо написать шаbлон оbёртку, который включит типизацию оbратно.


Это сообщение отредактировал(а) Леопольд - 27.11.2010, 19:59


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
GoldFinch
Дата 27.11.2010, 23:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 15
Всего: 26



mes, зачем было городить такой сложный код, передали бы туда сразу int* например, оно бы вообще упало %)

предложите тогда лучший код, чтоб работал в гцц
PM MAIL ICQ   Вверх
mes
Дата 27.11.2010, 23:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(GoldFinch @  27.11.2010,  22:15 Найти цитируемый пост)
mes, зачем было городить такой сложный код, передали бы туда сразу int* например, оно бы вообще упало %)

так в этом случае Вы могли бы свалить на ССЗБ.. а тут вы вроде и метод правильно получили... да не тот.. smile

Добавлено через 3 минуты и 20 секунд
единственный безопасный способ получить void*_адрес метода.. это взять его у статической прокси функции..
(т.е. без лишних телодвижений  увы никак)..



--------------------
PM MAIL WWW   Вверх
GoldFinch
Дата 27.11.2010, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 15
Всего: 26



поясню, этот код нужен чтобы передавать коллбэки на С++ в библиотеки с Си-интерфейсом.
естественно у function_with_callback будет в сигнатуре void() и void* и на каком-то этапе надо будет привести T* в void*

кстати пожалуй более интересный вариант это
Код

//------- Third-party library code ------
typedef void(*callback_t)(void*);
void function_with_callback(callback_t callback, void* param)
{
    callback(param);
}
//------- Our library code --------
template<class T>
void ftor_to_fn(void* that)
{
    (*(T*)that)();
}
//------- test ------
#include <iostream>
#include <boost/bind.hpp>
int main()
{
    struct Foo
    {
        void operator()() { std::cout << "test #1 OK\n"; }
        void bar() { std::cout << "test #2 OK\n"; }
        void baz() { std::cout << "test #3 OK\n"; }
    };
    Foo foo;
    
    function_with_callback(ftor_to_fn<Foo>, &foo);

    auto f1 = boost::bind(&Foo::bar, &foo);
    function_with_callback(ftor_to_fn<decltype(f1)>, &f1);
    
    auto f2 = [&foo](){ foo.baz(); };
    function_with_callback(ftor_to_fn<decltype(f2)>, &f2);
}


Добавлено через 4 минуты и 54 секунды
mes, я не понимаю. 
вы написали 
Код

function_with_callback(method_to_fn<Foo, &Foo::bar>, &afoo); // тип afoo != Foo

вторым аргументом function_with_callback может быть чтоугодно, 
по этому подразумевается что пользователь должен сам убедиться что если 1й аргумент это адаптер для T, то 2й аргумент имеет тип T*
PM MAIL ICQ   Вверх
mes
Дата 27.11.2010, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(GoldFinch @  27.11.2010,  22:30 Найти цитируемый пост)
что пользователь должен сам убедиться что если 1й аргумент это адаптер для T, то 2й аргумент имеет тип T*

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

Добавлено через 1 минуту и 30 секунд
Цитата(GoldFinch @  27.11.2010,  22:30 Найти цитируемый пост)
кстати пожалуй более интересный вариант это

этот уже похож на нормальный.. нужно внимательней посмотреть.. 



--------------------
PM MAIL WWW   Вверх
GoldFinch
Дата 27.11.2010, 23:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 15
Всего: 26



вот тут вот надо обязательно использовать дополнительную переменную
Цитата(GoldFinch @  28.11.2010,  00:30 Найти цитируемый пост)
    auto f2 = [&foo](){ foo.baz(); };
    function_with_callback(ftor_to_fn<decltype(f2)>, &f2);

этим можно воспользоваться, и написать вот так вот:

Код

//------- Third-party library code ------
typedef void(*callback_t)(void*);
void function_with_callback(callback_t callback, void* param)
{
    callback(param);
}
//------- Our library code --------
#include <utility>
template<class Functor>
std::pair<void(*)(void*), void*> ftor_to_fn_pair(Functor&& ftor)
{
    struct Wrap
    {
        static void invoke(void* that)
        {
            (*(Functor*)that)();
        }
    };    
    return std::pair<void(*)(void*), void*>(&Wrap::invoke, &ftor);
}
//------- test ------
#include <iostream>
int main()
{
    struct Foo
    {
        void bar() { std::cout << "test OK, x = " << x << "\n"; }
        int x;
        Foo(int x) : x(x) {}
    };
    Foo foo(42);
   
    auto f = ftor_to_fn_pair([&foo](){ foo.bar(); });
    function_with_callback(f.first, f.second);
}

вроде это наиболее типобезопасный вариант

Добавлено через 3 минуты и 24 секунды
интересно правда как этот код вообще работает %)
я не очень понимаю что есть rvalue-reference, и почему значение этой лямбды продолжает жить %)
PM MAIL ICQ   Вверх
mes
Дата 27.11.2010, 23:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(GoldFinch @  27.11.2010,  22:51 Найти цитируемый пост)
вроде это наиболее типобезопасный вариант

мне кажется тут еще можно подумать..

Добавлено через 1 минуту и 7 секунд
идти не в сторону получения пары, а предоставлении обертки над  function_with_callback


--------------------
PM MAIL WWW   Вверх
GoldFinch
Дата 28.11.2010, 00:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 15
Всего: 26



... и да, использование дополнительной локальной переменной делает всё совершенно неюзабельным =\
проблема в том, что она должна где-то жить, чтобы указатель на нее был валидным.

а типичный пример использования это
Код

    Foo* foo = get_Foo_instance();

    void set_handler(void(*)(void*), void*);
    set_handler(adapt_method_to_fn(&Foo::method), foo);



Добавлено через 1 минуту и 18 секунд
пара полезна тем что она гарантирует то, что оба агрумента взяты из одного источника, который может проверить их совместимость

Добавлено через 4 минуты и 26 секунд
Цитата(mes @  28.11.2010,  00:57 Найти цитируемый пост)
предоставлении обертки над  function_with_callback 

это наиболее очевидный и понятный вариант, но мы его не рассматриваем.

мне интересно создание одной реюзабельной функции которая позволила бы делать обертки для методов

Добавлено через 12 минут и 11 секунд
более того, есть случаи, когда написание обертки практически невозможно
Код

void fn(void(*callback)(void*), void* param, const char* format, ... /*ellipsis*/);

PM MAIL ICQ   Вверх
mes
Дата 28.11.2010, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(GoldFinch @  27.11.2010,  23:05 Найти цитируемый пост)
мне интересно создание одной реюзабельной функции которая позволила бы делать обертки для методов

ну а что мешает сделать это проксю единой для всех подходящих функций ?
 smile

Добавлено @ 00:28
Цитата(GoldFinch @  27.11.2010,  23:05 Найти цитируемый пост)
более того, есть случаи, когда написание обертки практически невозможно

ну еллипсис впринципе можно тоже разгрузить..

другой вопрос - нужно ли это..

Это сообщение отредактировал(а) mes - 28.11.2010, 00:34


--------------------
PM MAIL WWW   Вверх
mes
Дата 28.11.2010, 00:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



вот примерно о чем я предлагал  (на основе вашего кода)
Код

template <typename F1, typename F2>
void proxy (F1 && f1, F2&&  f2)
{
    struct Wrap
    {
        static void invoke(void* that)
        {
            (*(F2*)that)();
        }
    }; 
    f1 (&Wrap::invoke, &f2);
}

 Foo foo(42);
    
 proxy ( std::bind(fcb,_1,_2) 
       , std::bind(&Foo::bar,&foo) );


fcb - function_with_callback


--------------------
PM MAIL WWW   Вверх
Леопольд
Дата 28.11.2010, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



mes, думается, это надо для реального проекта. Навряд ли rvalue ссылки можно в нём использовать. Правда, ничто не мешает из заменить на оbычные... smile


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
mes
Дата 28.11.2010, 01:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Леопольд @  27.11.2010,  23:59 Найти цитируемый пост)
Навряд ли rvalue 

я их у тс перенял smile раз ему можно , значит все в порядке  smile

Добавлено @ 01:03
тем более они к теме напрямую не относятся..
и вопрос о надежности уже был также поднят тс.. но я например не в состоянии на него ответить.. поэтому пока беру как есть smile

Добавлено @ 01:04
суть в самом вызове proxy, чтоб не приходилось в ручную заниматься "подбором" параметров.. 


Это сообщение отредактировал(а) mes - 28.11.2010, 01:05


--------------------
PM MAIL WWW   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0616 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.