TimPP
Гость
|
|
« : 04-10-2004 13:03 » |
|
Вопрос в крепком шаблоновом завороте. Нужно сделать, что бы шаблоновая функция вызывала, метод класса когда мне нужно, типа: class ClassA { void Foo ( int ) { .... } void Foo1 ( int ) { .... } }; template < class _Cl, void (_Cl::*_Fn) ( int ) > void TpCall ( ClassA* aObject, int a ) { (aObject->*_Fn) ( a ) } где, то глубоко в коде... ClassA _Class; TpCall < ClassA, ClassA::Foo > ( &_Class, 10 ); TpCall < ClassA, ClassA::Foo1 > ( &_Class, 10 ); // вызывает Foo проблема в том, что такая функция создается одна и при попытке вызвать другую функцию класса вызывает только ту которая первая была зарегистрирована Спасибо!
|
|
|
Записан
|
|
|
|
Serega
Гость
|
|
« Ответ #1 : 04-10-2004 13:13 » |
|
Подобную проблему мы уже обсуждали
|
|
|
Записан
|
|
|
|
TimPP
Гость
|
|
« Ответ #2 : 04-10-2004 13:48 » |
|
Не, не та ситуация. Может я немного не правильно объяснил. Есть С-шная библиотека которая регистрирует и запускает функции ( получается статические ), но в качестве параметра в эту функцию передает структуру ( класс в котором нужно вызвать метод ) от которой я могу наследоваться. Я пишу библиотеку, количество классов и методов мне не известно. Нужно сделать, что бы была шаблоновая функция которая бы неявно связывала вызов из С-шной библы с вызовом метода класса. Т.е. неявно создавалась статическая функция, которая регистрируется в Си и может вызвать ( только один, определенный! ) метод у передаваемого ей класса. Пример желаемой регистрации: class ClassA : public BaseStruct { public: void Foo1 ( int ); void Foo2 ( int ); };
ClassMethods Methods [] = { MyReg < ClassA, ClassA::Foo1 > (), MyReg < ClassA, ClassA::Foo2 > () };
... ClassReg ( "ClassA", Methods ); ...
Библиотека Си (вызов)-> SameStaticFunc_Foo1 (ClassA*) -> ClassA::Foo1 Библиотека Си (вызов)-> SameStaticFunc_Foo2 (ClassA*) -> ClassA::Foo2
|
|
« Последнее редактирование: 01-12-2007 16:47 от Алексей1153++ »
|
Записан
|
|
|
|
NetRaider
Гость
|
|
« Ответ #3 : 04-10-2004 23:36 » |
|
ClassA _Class; TpCall < ClassA, ClassA::Foo > ( &_Class, 10 ); TpCall < ClassA, ClassA::Foo1 > ( &_Class, 10 ); // вызывает Foo проблема в том, что такая функция создается одна и при попытке вызвать другую функцию класса вызывает только ту которая первая была зарегистрирована Так и должно быть, - сигнатуры ведь одинаковы. Как вариант - передавать в TpCall указатель на функцию. Как другой вариант : template<class T> class function_shim { const T& base; typedef void (T::*function_type)(int); std::map<const char*, function_type> native_func; public: function_shim(const T& b):base(b)| }
void reg(const char* name, function_type fn) { native_func[name] = fn; }
void exec(const char* name, int p) { function_type fn = native_func[name]; assert(fn != 0); (base.*native_func[name])(p); } };
struct A { A():shim(*this) { shim.reg("foo1", foo1); shim.reg("foo2", foo2); } void foo1(int){ }
void foo2(int){ }
function_shim<A> shim; };
/*...*/
a.shim.exec("foo1", 10);
|
|
« Последнее редактирование: 01-12-2007 16:55 от Алексей1153++ »
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #4 : 05-10-2004 09:35 » |
|
Да мы только что об этом говорили, ну я еще раз повторю, можно так template <class T, class Ret, class Param> struct functor { T * object; Ret (T::*function)(Param);
functor (Ret (T::*_function)(Param), T * _object) : object(_object), function(_function) {}
Ret operator()(Param param) { return (object->*function)(param); } }; class A { public: int f1(int p) | return 2* p; }; int f2(int p) | return p; }; };
void main() { A a; functor<A, int, int> f1(&A::f1, &a); functor<A, int, int> f2(&A::f2, &a);
int result1 = f1(10); int result2 = f2(10); }
(есть такая штука называется функтор!!!!, если само слово не нравится можно его инкапсулировать в функцию)
|
|
« Последнее редактирование: 01-12-2007 16:56 от Алексей1153++ »
|
Записан
|
С уважением Lapulya
|
|
|
TimPP
Гость
|
|
« Ответ #5 : 06-10-2004 06:37 » |
|
У меня появилась одна идея, но я не знаю пока как ее реализовать. Может быть можно как-нибудь создавать шаблон с разной сигнатурой, там например, наследник последнего использованного? Но вопрос, как хранить тип последнего использованного? template < class _Cl, class _Counter = (каждый раз, новый тип) > class Redirector { public: ... ... ... };
... Redirector < SomeClass > _Redir; ...
|
|
« Последнее редактирование: 01-12-2007 16:58 от Алексей1153++ »
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #6 : 06-10-2004 07:07 » |
|
TimPP, Ты прочитай то, что я своим первым постом-то запостил Там уже написано решение твоей проблемы (и в красках)
|
|
|
Записан
|
С уважением Lapulya
|
|
|
Anonymous
Гость
|
|
« Ответ #7 : 06-10-2004 09:23 » |
|
TimPP, Ты прочитай то, что я своим первым постом-то запостил Там уже написано решение твоей проблемы (и в красках) Повторюсь, std`шные приемы типа mem_fun (который ты привел), негодятся . Т.к. Си-шной библиотеке подавай указатель на функцию для вызова. Нужно, не явно, создать эту функцию (статическую), а потом эта функция по передаваемому ей параметру (указателю на класс) должна вызвать ОПРЕДЕЛЕННУЮ функцию класса.
|
|
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #8 : 06-10-2004 10:07 » |
|
Да я ж написал... ... если само слово не нравится можно его инкапсулировать в функцию
вот так например template <class T, class Ret, class Param> struct functor { T * object; Ret (T::*function)(Param);
functor (Ret (T::*_function)(Param), T * _object) : object(_object), function(_function) {}
Ret operator()(Param param) { return (object->*function)(param); } }; class A { public: int f1(int p) { return 2* p; }; int f2(int p) { return p; }; };
template <class T, class Ret, class Param> static Ret Just_A_Simple_Function_It_Is_A_Static(Ret (T::*function)(Param), T * object, Param param) { functor<A, int, int> f(function, object); return f(param); }
void main() { A a; // functor<A, int, int> f1(&A::f1, &a); // functor<A, int, int> f2(&A::f2, &a);
// int result1 = f1(10); // int result2 = f2(10);
int result1 = Just_A_Simple_Function_It_Is_A_Static<A, int, int>(&A::f1, &a, 10); int result2 = Just_A_Simple_Function_It_Is_A_Static<A, int, int>(&A::f2, &a, 10); }
здесь Just_A_Simple_Function_It_Is_A_Static - чисто статическая функция... чище не бывает
|
|
« Последнее редактирование: 01-12-2007 17:00 от Алексей1153++ »
|
Записан
|
С уважением Lapulya
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #9 : 06-10-2004 10:47 » |
|
Если тебя плющит и колбасит только от одной мысли, что у тебя в программе используется функтор (о боже функтор!), то можно и от этого избавиться, кодить чуть меньше, но выполняться возможно (а как правило так оно и есть) будет дольше.... мммм хотя не, гоню так и так поинтер на функцию передается, => в двух последних вариантах вроде разницы в скорости выполнения быть не должно... class A { public: int f1(int p) { return 2* p; }; int f2(int p) { return p; }; };
template <class T, class Ret, class Param> static Ret Just_A_Simple_Function_It_Is_A_Static(Ret (T::*function)(Param), T * object, Param param) { return (object->*function)(param); }
void main() { A a;
int result1 = Just_A_Simple_Function_It_Is_A_Static<A, int, int>(&A::f1, &a, 10); int result2 = Just_A_Simple_Function_It_Is_A_Static<A, int, int>(&A::f2, &a, 10); }
ну или что-то в этом роде...
|
|
« Последнее редактирование: 01-12-2007 17:02 от Алексей1153++ »
|
Записан
|
С уважением Lapulya
|
|
|
TimPP
Гость
|
|
« Ответ #10 : 06-10-2004 11:48 » |
|
Да, есть только мааааленькая проблема. Вызов должен быть следующим: int result1 = Just_A_Simple_Function_It_Is_A_Static_BUT_JUST_FOR_F1<A, int, int>(&A, &a, 10); int result1 = Just_A_Simple_Function_It_Is_A_Static_BUT_JUST_FOR_F2<A, int, int>(&A, &a, 10);
Потому, что вызывается по указателю! И указателю я должен назначить функцию БЕЗ параметров .
|
|
« Последнее редактирование: 01-12-2007 17:04 от Алексей1153++ »
|
Записан
|
|
|
|
TimPP
Гость
|
|
« Ответ #11 : 06-10-2004 11:52 » |
|
Извиняюсь, вот так: int result1 = Just_A_Simple_Function_It_Is_A_Static_BUT_JUST_FOR_F1<A, int>(&a, 10);
|
|
« Последнее редактирование: 01-12-2007 17:05 от Алексей1153++ »
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #12 : 06-10-2004 13:40 » |
|
TimPP, чего то не могу понять чего требуется ... ммммм в чем отличие этого int res = function<A, int, int>(&A::f2, &a, 10);
от этого int res = function<A, int>(&a, 10);
применительно к данной задаче, не нравится что три параметра передается в функцию а не два .... ммммммм или что шаблон инстацируется тремя типами, а не двумя или что .... короче уточни что же именно неустраивает и еще не могу понять этой загадочной фразы Потому, что вызывается по указателю! И указателю я должен назначить функцию БЕЗ параметров .
и пример int result1 = Just_A_Simple_Function_It_Is_A_Static_BUT_JUST_FOR_F1<A, int>(&a, 10);
говоришь без параметров а тут их аж два, да и еще, я и свою функцию (вот эту тоесть) template <class T, class Ret, class Param> static Ret Just_A_Simple_Function_It_Is_A_Static(Ret (T::*function)(Param), T * object, Param param);
запросто могу по указателю на нее вызвать. Короче треба еще инфы, чтобы так сказать вникнуть в суть вопроса
|
|
« Последнее редактирование: 01-12-2007 17:06 от Алексей1153++ »
|
Записан
|
С уважением Lapulya
|
|
|
TimPP
Гость
|
|
« Ответ #13 : 06-10-2004 14:52 » |
|
Ну хорошо. Есть язык Python, у него есть интерфейс написания модулей на Си. Пишу С++ врапер для этого интерфейса (есть другие разработки, но они не устраивают). Так вот, в питоне есть классы, на Си они реализованы как структуры, назначаешь функцию как метод и в нее приходит эта структура как аргумент и ты ее колбасишь, тоесть: struct PyClass { ... };
typedef void (*PyClassMethod) ( PyClass*, int );
void MyMethod ( PyClass*, int ) { ... }
struct PyMethods [] = { { "Foo1", MyMethod } };
... RegClass ( "SameClass", sizeof((struct)PyClass), PyMethods ); ...
Я хочу все это превратить в настоящий класс. Для этого пытаюсь делаю так: template < class _T > struct _MyPyClassStruct { ... _T object; };
class MyPyClass { void Foo ( int ); ... };
struct PyMethods [] = { <СУПЕР_ФУНКЦИЯ_РЕГИСТРАЦИИ_ДАЮЩАЯ_ТИП_PyClassMethod>{ "Foo1", MyPyClass::Foo } };
RegClass <MyPyClass> ( "SameClass", PyMethods );
Вызов по идее должен быть: Питон (ч/з указатель) => Static_Func_Foo( _MyPyClassStruct<MyPyClass>* A, int B) => A->Foo ( B ) Примерно так...
|
|
« Последнее редактирование: 01-12-2007 17:08 от Алексей1153++ »
|
Записан
|
|
|
|
lapulya
Молодой специалист
Offline
|
|
« Ответ #14 : 07-10-2004 08:11 » |
|
тут дело в чем? получается, что сигнатура функции жестко задана (насколько я понимаю), ну так например... void MyMethod ( PyClass*, int )
поэтому как параметр - указатель на функцию мембер не прокатывает ... далее надо учесть что при инстацировании шаблона юзаются ТИПЫ :!: :!: :!: а не значения, поэтому возможны лишь некоторые шаманства с чистыми шаблонами или шаблонами и подручными средствами... если не пугают дефайны, можно так #define function(Function, static_func) \ template <class T> \ static int static_func(T * object, int param)\ {\ return object->Function(param);\ }
class A { public: int f1(int p) | return 2* p; }; int f2(int p) | return p; }; };
function(f1, stat_f1); function(f2, stat_f2);
void main() { A a;
int result1 = stat_f1<A> ( &a, 10 ); int result2 = stat_f2<A> ( &a, 10 ); }
хотя честно скажу я это считаю полным отстоем... :oops: :oops: ща еще подумаю как бы мне тут без дефайнов обойтись
|
|
« Последнее редактирование: 01-12-2007 17:13 от Алексей1153++ »
|
Записан
|
С уважением Lapulya
|
|
|
TimPP
Гость
|
|
« Ответ #15 : 07-10-2004 09:06 » |
|
Да, дефайны очень не здорово. :new_shot:
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #16 : 14-04-2006 19:08 » |
|
Думаю, пока в архив.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
|