Спецификация функции-члена в ключевом слове template
От: Virtus  
Дата: 04.03.08 10:24
Оценка:
Вопрос по шаблонам, подскажите, пожалуйста...
Мне требуется передавать в шаблонные функции указатели на функции-члены различных классов.
Причем сигнатура функций-членов классов одинаковая — это callback'и. Внутри шаблонной функции
создается объект шаблонного класса — функтор, который впоследствии при возникновении опреде-
ленного события передаст управление связанному с ним обработчику — функции-члену.
Псевдокод:

template <class T>
void CBasic::connect_activate_mouse( T* pObj, int ( T::*pMFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) ) {
connect( CB_REASON_LEFTBUTTON_UP, new TFunctor<T>( pObj, pMFn ) );
}

template <class T>
void CBasic::connect_activate_key( T* pObj, int ( T::*pMFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) ) {
connect( CB_REASON_KEY_DOWN, new TFunctor<T>( pObj, pMFn ) );
}

Хотелось бы вынести полную спецификацию функции-члена в ключевое слово template, вместо указатия
ее в параметрах функции:

template <class T, typename int ( T::*MemFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) >
void CBasic::connect_activate_mouse( T* pObj, MemFn pMFn ) {
connect( CB_REASON_LEFTBUTTON_UP, new TFunctor<T>( pObj, pMFn ) );
}

template <class T, typename int ( T::*MemFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) >
void CBasic::connect_activate_key( T* pObj, MemFn pMFn ) {
connect( CB_REASON_KEY_DOWN, new TFunctor<T>( pObj, pMFn ) );
}

Но такой вариант не компилируется...
Встречал еще такой вариант, но здесь по-моему идет речь о значении по-умолчанию:

template<typename T, typename F = bool (T::*)(CDC*)>
PaintMessageHandler(T* obj, const F& f = &T::OnDraw)
{
return PaintMessageHandler(obj, boost::bind(f, obj, _1));
}
Re: Спецификация функции-члена в ключевом слове template
От: Bell Россия  
Дата: 04.03.08 10:49
Оценка: +1
Здравствуйте, Virtus, Вы писали:

V>Хотелось бы вынести полную спецификацию функции-члена в ключевое слово template, вместо указатия

V>ее в параметрах функции:
V> template <class T,  typename int ( T::*MemFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) >
V> void CBasic::connect_activate_mouse( T* pObj, MemFn pMFn ) {
V>  connect( CB_REASON_LEFTBUTTON_UP, new TFunctor<T>( pObj, pMFn ) );
V> }


Сначала абстрактный вопрос: Зачем? Чего хочется достичь?
Любите книгу — источник знаний (с) М.Горький
Re[2]: Спецификация функции-члена в ключевом слове template
От: zaufi Земля  
Дата: 04.03.08 11:24
Оценка:
Здравствуйте, Bell, Вы писали:

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


V>>Хотелось бы вынести полную спецификацию функции-члена в ключевое слово template, вместо указатия

V>>ее в параметрах функции:
B>
V>> template <class T,  typename int ( T::*MemFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) >
V>> void CBasic::connect_activate_mouse( T* pObj, MemFn pMFn ) {
V>>  connect( CB_REASON_LEFTBUTTON_UP, new TFunctor<T>( pObj, pMFn ) );
V>> }
B>


B>Сначала абстрактный вопрос: Зачем? Чего хочется достичь?


очевидна краткости записи и четабельности кода
Re[3]: Спецификация функции-члена в ключевом слове template
От: Bell Россия  
Дата: 04.03.08 11:28
Оценка:
Здравствуйте, zaufi, Вы писали:

B>>Сначала абстрактный вопрос: Зачем? Чего хочется достичь?


Z>очевидна краткости записи и четабельности кода


Исходный вариант:
template <class T>
void CBasic::connect_activate_mouse( T* pObj, int ( T::*pMFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) )



Желаемый вариант:
template <class T, typename int ( T::*MemFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) >
void CBasic::connect_activate_mouse( T* pObj, MemFn pMFn )


Ы?
Любите книгу — источник знаний (с) М.Горький
Re[4]: Спецификация функции-члена в ключевом слове template
От: zaufi Земля  
Дата: 04.03.08 11:29
Оценка: :)
Здравствуйте, Bell, Вы писали:

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


B>>>Сначала абстрактный вопрос: Зачем? Чего хочется достичь?


Z>>очевидна краткости записи и четабельности кода


B>Ы?

смайлег в конце.. ЫЫЫ ))
Re[4]: Спецификация функции-члена в ключевом слове template
От: Virtus  
Дата: 04.03.08 12:01
Оценка:
Z>>очевидна краткости записи и четабельности кода

B>Исходный вариант:

B>
B>template <class T>
B>void CBasic::connect_activate_mouse( T* pObj, int ( T::*pMFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) )
B>



B>Желаемый вариант:

B>
B>template <class T, typename int ( T::*MemFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) >
B>void CBasic::connect_activate_mouse( T* pObj, MemFn pMFn ) 
B>


B>Ы?


Совершенно верно, краткость записи. Предположим, что указатель на функцию-член класса не
единственный параметр шаблонной функции, описывать набор параметров в нескольких строках...
к тому же таких шаблонных функций может быть определено несколько — на некоторые стандартные
события. Интересно и другое: здесь в ключевом слове template второй параметр зависит от типа первого параметра.
Re[5]: Спецификация функции-члена в ключевом слове template
От: Bell Россия  
Дата: 04.03.08 14:43
Оценка:
Здравствуйте, Virtus, Вы писали:


Z>>>очевидна краткости записи и четабельности кода


B>>Исходный вариант:

B>>
B>>template <class T>
B>>void CBasic::connect_activate_mouse( T* pObj, int ( T::*pMFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) )
B>>



B>>Желаемый вариант:

B>>
B>>template <class T, typename int ( T::*MemFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) >
B>>void CBasic::connect_activate_mouse( T* pObj, MemFn pMFn ) 
B>>


B>>Ы?


V>Совершенно верно, краткость записи. Предположим, что указатель на функцию-член класса не

V>единственный параметр шаблонной функции, описывать набор параметров в нескольких строках...
А записывать набор параметров шаблона в нескольких строках?

V>к тому же таких шаблонных функций может быть определено несколько — на некоторые стандартные

V>события.

И что?

V>Интересно и другое: здесь в ключевом слове template второй параметр зависит от типа первого параметра.

Интересно то, что запись
template<typename T, typename F = bool (T::*)(CDC*)>
PaintMessageHandler(T* obj, const F& f = &T::OnDraw)

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

В общем по-прежнему ничего не понятно
Но если так хочется краткости, то можно сделать так:
template <class T, class MemFn>
void CBasic::connect_activate_mouse( T* pObj, MemFn pMFn ) {
connect( CB_REASON_LEFTBUTTON_UP, new TFunctor<T>( pObj, pMFn ) );
}

template <class T, typename MemFn>
void CBasic::connect_activate_key( T* pObj, MemFn pMFn ) {
connect( CB_REASON_KEY_DOWN, new TFunctor<T>( pObj, pMFn ) );
}
Любите книгу — источник знаний (с) М.Горький
Re[5]: Спецификация функции-члена в ключевом слове template
От: zaufi Земля  
Дата: 04.03.08 15:42
Оценка: 2 (1)
Здравствуйте, Virtus, Вы писали:

B>>Желаемый вариант:

B>>
B>>template <class T, typename int ( T::*MemFn )( CWidget* widget, PtCallbackInfo_t* cbinfo ) >
B>>void CBasic::connect_activate_mouse( T* pObj, MemFn pMFn ) 
B>>


B>>Ы?


V>Совершенно верно, краткость записи. Предположим, что указатель на функцию-член класса не

V>единственный параметр шаблонной функции, описывать набор параметров в нескольких строках...
V>к тому же таких шаблонных функций может быть определено несколько — на некоторые стандартные
V>события. Интересно и другое: здесь в ключевом слове template второй параметр зависит от типа первого параметра.

ну как вариант "затайпдефить" этот указатель с помощью "traits"

// наопределять таких 'traits' можно по числу желаемых функций с разными там параметрами и все такое...
template <typename T>
struct callback_traits
{
    typedef int (T::*type)(CWidget*, PtCallbackInfo_t*);
};

template <class T>
void CBasic::connect_activate_mouse(T* pObj,  typename callback_traits<T>::type f)
{
  // ....
}


еще возможный вариант работать с boost::function<int(CWidget*,PtCallbackInfo_t*)> вместа голых уазателей на функции и байндить их по мере надобности...
Re[6]: Спецификация функции-члена в ключевом слове template
От: Virtus  
Дата: 05.03.08 08:32
Оценка:
Здравствуйте, Bell, Вы писали:

V>>Интересно и другое: здесь в ключевом слове template второй параметр зависит от типа первого параметра.

B>Интересно то, что запись
B>
B>template<typename T, typename F = bool (T::*)(CDC*)>
B>PaintMessageHandler(T* obj, const F& f = &T::OnDraw)
B>

B>некорректна, т.к. текущий стандарт не позволяет использовать умолчательные аргументы для параметров шаблонов функций

Bell, спасибо. Вы оказались правы, default-аргументы разрешены только в
шаблонных классах... Откомпилировал примерчик и сам в этом убедился...

E:\>cl.exe memfunc.cpp /EHsc
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

memfunc.cpp
memfunc.cpp(25) : error C4519: default template arguments are only allowed on a class template; ignored
Re[6]: Спецификация функции-члена в ключевом слове template
От: Virtus  
Дата: 05.03.08 08:36
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>ну как вариант "затайпдефить" этот указатель с помощью "traits"

Z>

Z>// наопределять таких 'traits' можно по числу желаемых функций с разными там параметрами и все такое...
Z>template <typename T>
Z>struct callback_traits
Z>{
Z>    typedef int (T::*type)(CWidget*, PtCallbackInfo_t*);
Z>};

Z>template <class T>
Z>void CBasic::connect_activate_mouse(T* pObj,  typename callback_traits<T>::type f)
Z>{
Z>  // ....
Z>}
Z>


zaufi, спасибо. Вариант с объявлением типа в структуре прекрасно работает
и теперь не приходится каждый раз перечилять все аргументы функций-членов
при определении шаблонных функций. +1
Re[7]: Спецификация функции-члена в ключевом слове template
От: zaufi Земля  
Дата: 05.03.08 11:51
Оценка:
Здравствуйте, Virtus, Вы писали:

V> zaufi, спасибо. Вариант с объявлением типа в структуре прекрасно работает

V> и теперь не приходится каждый раз перечилять все аргументы функций-членов
V> при определении шаблонных функций. +1

и всетаки я бы присмотрелся к boost::function... и почитал бы про boost::signals -- чтоб не изобретать велосипедов... мне кажется у тя какаято родственная задача... если ты не пользуешь какойта готовый framework то стоит обратить внимание...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.