Здравствуйте, Аноним, Вы писали:
А>Подскажите, как написать что-то такое
Для начала расскажи сценарий использования этой фичи.
Re[2]: шаблоны
От:
Аноним
Дата:
15.03.06 10:49
Оценка:
Здравствуйте, Alxndr, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
А>>Подскажите, как написать что-то такое
A>Для начала расскажи сценарий использования этой фичи.
Сценарий приблизительно такой:
struct Callback
{
void (*f1)( int p1, void * pCtx );
void (*f2)( double p2, void * pCtx );
};
void mega_algo( Callback * pCallback, void * pCtx )
{
...
pCallback->f1( 34, pCtx );
...
}
class C1
{
void f()
{
Callback callback;
callback.f1 = ...(cb_f1); /* вот тут что-то написать, что-бы вызов шел на C1::cb_f1() */
callback.f2 = ...(cb_f2); /* вот тут что-то написать, что-бы вызов шел на C1::cb_f2() */
mega_algo( &callback, this );
}
void cb_f1( int p1 );
void cb_f2( double p2 );
};
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Alxndr, Вы писали:
A>>Здравствуйте, Аноним, Вы писали:
А>>>Подскажите, как написать что-то такое
A>>Для начала расскажи сценарий использования этой фичи.
А>Сценарий приблизительно такой:
А>
А>struct Callback
А>{
А> void (*f1)( int p1, void * pCtx );
А> void (*f2)( double p2, void * pCtx );
А>};
А>void mega_algo( Callback * pCallback, void * pCtx )
А>{
А> ...
А> pCallback->f1( 34, pCtx );
А> ...
А>}
А>class C1
А>{
А> void f()
А> {
А> Callback callback;
А> callback.f1 = ...(cb_f1); /* вот тут что-то написать, что-бы вызов шел на C1::cb_f1() */
А> callback.f2 = ...(cb_f2); /* вот тут что-то написать, что-бы вызов шел на C1::cb_f2() */
А> mega_algo( &callback, this );
А> }
А> void cb_f1( int p1 );
А> void cb_f2( double p2 );
А>};
А>
Не понятно, какое отношение это имеет к первому вопросу.
И как быть с void * pCtx? Сигнатуры функций не совпадают.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, remark, Вы писали: R>>Не понятно, какое отношение это имеет к первому вопросу. А>отношение не очевидное
R>>И как быть с void * pCtx? Сигнатуры функций не совпадают. А>void * pCtx должен превратится в this А>идея в том чтоб шаблонами создавались функции вроде
А покороче синтаксис нельзя?
Вроде есть какая-то "argument deduction" и если ее применить можно не писать int и double в аргуменрах шаблона — они будут дедуктится.
R>Лови:
R>
Здравствуйте, Аноним, Вы писали:
А>А покороче синтаксис нельзя? А>Вроде есть какая-то "argument deduction" и если ее применить можно не писать int и double в аргуменрах шаблона — они будут дедуктится.
У меня у самого и была такая задумка изначально:
make_wrapper(&C1::cb_f1);
Но тут как-то сложно получается из-за указателей на функции-члены...
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Аноним, Вы писали:
А>>А покороче синтаксис нельзя? А>>Вроде есть какая-то "argument deduction" и если ее применить можно не писать int и double в аргуменрах шаблона — они будут дедуктится.
R>У меня у самого и была такая задумка изначально:
R>
R>make_wrapper(&C1::cb_f1);
R>
R>Но тут как-то сложно получается из-за указателей на функции-члены...
Это нужно только для одного класса C1 или для многих?
Типов параметров (int, double) ограниченное количество или могут быть любые?
R>>Это нужно только для одного класса C1 или для многих? R>>Типов параметров (int, double) ограниченное количество или могут быть любые?
А>Ну, конечно, желетельно, для многих классов и для любых, но если есть решение при каких-то ограничениях — мне тоже будет интересно посмотреть.
template< typename Function>
struct wrapper;
template< typename Ret, class Class >
struct wrapper< Ret (Class::*) () >
{
template< Ret (Class::*fn) () >
Ret call ( void * ptr) {
return ( static_cast<Class *> (ptr)->*(fn) ) (a);
}
};
template< typename Ret, class Class, typename Arg1 >
struct wrapper<Ret (Class::*) (Arg1)>
{
template< Ret (Class::*fn) (Arg1) >
static Ret call ( Arg1 a, void * ptr) {
return ( static_cast<Class *> (ptr)->*(fn) ) (a);
}
};
... и далее пока руки не отвалятся
использовать wrapper<void (test::*)(int)>::call<&test::f1>
R>>Это нужно только для одного класса C1 или для многих? R>>Типов параметров (int, double) ограниченное количество или могут быть любые?
А>Ну, конечно, желетельно, для многих классов и для любых, но если есть решение при каких-то ограничениях — мне тоже будет интересно посмотреть.
... всё же сложно получается...
Если есть возможность проще как-то переделать хранение калбек функций, чтобы без void* и что-бы всё было типобезопасное и на шаблонах
Здравствуйте, remark, Вы писали:
R>Здравствуйте, night beast, Вы писали:
NB>>... и далее пока руки не отвалятся
R>Что бы руки не отваливались помогает boost.preprocessor — очень рекомендую
NB>>использовать wrapper<void (test::*)(int)>::call<&test::f1>
R>В моём варианте и то проще использовать
твой вариант расчитан на один аргумент у функции, а здесь -- сколько влезет.
а если еще расширения подключить, то вот так
Здравствуйте, night beast, Вы писали:
NB>твой вариант расчитан на один аргумент у функции, а здесь -- сколько влезет. NB>а если еще расширения подключить, то вот так
NB>
// либо так (два раза указывать функцию):
callback.f1 = make_adapter_traits(&C1::cb_f1).adapter<&C1::cb_f1>;
callback.f2 = make_adapter_traits(&C1::cb_f2).adapter<&C1::cb_f2>;
// либо так
callback.f1 = MAKE_ADAPTER(&C1::cb_f1);
callback.f2 = MAKE_ADAPTER(&C1::cb_f2);
_>Можно и без typeof обойтись:
_>Варианты использования: _>
_>// либо так (два раза указывать функцию):
_>callback.f1 = make_adapter_traits(&C1::cb_f1).adapter<&C1::cb_f1>;
_>callback.f2 = make_adapter_traits(&C1::cb_f2).adapter<&C1::cb_f2>;
_>// либо так
_>callback.f1 = MAKE_ADAPTER(&C1::cb_f1);
_>callback.f2 = MAKE_ADAPTER(&C1::cb_f2);
_>
это уже дома подумалось
только вместо make_adapter_traits(&C1::cb_f2).adapter<&C1::cb_f2>;
надо make_adapter_traits(&C1::cb_f2).instance<&C1::cb_f2>();,
которая возвращает adapter<&C1::cb_f2>.
без этого комо не компилирует...
недостатки метода -- это не compile-time константа.