Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Короли шаблонов, требуются!!!  (Прочитано 19114 раз)
0 Пользователей и 1 Гость смотрят эту тему.
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 » 

Цитата: TimPP
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
Молодой специалист

ru
Offline 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
Молодой специалист

ru
Offline Offline

« Ответ #6 : 06-10-2004 07:07 » 

TimPP, Ты прочитай то, что я своим первым постом-то запостил Жжешь Там уже написано решение твоей проблемы (и в красках)
Записан

С уважением Lapulya
Anonymous
Гость
« Ответ #7 : 06-10-2004 09:23 » 

Цитата: lapulya
TimPP, Ты прочитай то, что я своим первым постом-то запостил Жжешь Там уже написано решение твоей проблемы (и в красках)


Повторюсь, std`шные приемы типа mem_fun (который ты привел), негодятся Жаль . Т.к. Си-шной библиотеке подавай указатель на функцию для вызова. Нужно, не явно, создать эту функцию (статическую), а потом эта функция по передаваемому ей параметру (указателю на класс) должна вызвать ОПРЕДЕЛЕННУЮ функцию класса.
Записан
lapulya
Молодой специалист

ru
Offline 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
Молодой специалист

ru
Offline 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
Молодой специалист

ru
Offline 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
Молодой специалист

ru
Offline 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
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 14-04-2006 19:08 » new

Думаю, пока в архив.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines