Шрифт:
Интервал:
Закладка:
template<class R>
struct gen_mem_fun_traits {
template<class T>
struct signature {
typedef gen_mem_fun_base_t<R, T> base;
};
};
template<> struct gen_mem_fun_traits<void> {
template<class T> struct signature {
typedef void_gen_mem_fun_base_t<T> base;
};
};
Этот класс специализирован для специального случая функции, возвращающей void. Таким образом, хоть нам и придется ввести дополнительный класс для функций, возвращающих void, для клиента это будет выглядеть единообразно: gen_mem_fun_traits<rettype>::signature<memberclass>::base.
Сами по себе ветви вычислений различных вариантов тривиальны:
template<class R, class T>
struct gen_mem_fun_base_t {
protected:
gen_mem_fun_base_t(R (T::*pm_)()): pm(pm_) {}
public:
template<class TT> R operator()(TT p) {return (p.operator->()->*pm)();}
template<> R operator()(T* p) {return (p->*pm)();}
private:
R (T::*pm)();
};
template<class T>
struct void_gen_mem_fun_base_t {
protected:
void_gen_mem_fun_base_t(void (T::*pm_)()): pm(pm_) {}
public:
template<class TT> void operator()(TT p) {(p.operator->()->*pm)();}
template<> void operator()(T* p) {(p->*pm)();}
private:
void (T::*pm)();
};
Теперь определим сам gen_mem_fun_t:
template<class R, class T>
struct gen_mem_fun_t: gen_mem_fun_traits<R>::template signature<T>::base {
typedef gen_mem_fun_traits<R>::template signature<T>::base base_;
explicit gen_mem_fun_t(R (T::*pm_)()): base_(pm_) {}
};
Один момент здесь требует пояснения: typedef используется для того, чтобы компилятор понял, какому предку нужно передать в конструктор наш указатель на функцию-член.
И, наконец, gen_mem_fun вообще остался без изменений:
template<class R, class T>
gen_mem_fun_t<R, T> gen_mem_fun(R (T::*pm)()) {
return gen_mem_fun_t<R, T>(pm);
}
Заключение
Надеюсь, читатель понял, что создание адаптера как такового не было основной целью этой статьи, тем более что гораздо более общий вариант такого адаптера под названием bind находится в библиотеке boost. Основная задача, которая стояла передо мной, была такова: дать читателю некоторые навыки и умения, позволяющие не пасовать перед необходимостью внести какие-либо дополнения или изменения в STL, а также познакомить с некоторыми приемами, специфичными для C++ и полезными при необходимости работать с компиляторами, не вполне поддерживающими стандарты.
Я благодарю Павла Кузнецова и Андрея Тарасевича за плодотворную дискуссию в форуме, непосредственно предшествовавшую написанию этой статьи и давшую мне некоторые приемы и идеи, которые были освещены выше.
- C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц - Программирование
- Язык программирования Euphoria. Справочное руководство - W Cat - Программирование
- РУКОВОДСТВО ПО СТАНДАРТНОЙ БИБЛИОТЕКЕ ШАБЛОНОВ (STL) - Александр Степанов - Программирование
- C# 4.0: полное руководство - Герберт Шилдт - Программирование
- Стандарты программирования на С++. 101 правило и рекомендация - Герб Саттер - Программирование
- QT 4: программирование GUI на С++ - Жасмин Бланшет - Программирование
- Сделай видеоигру один и не свихнись - Слава Грис - Программирование / Руководства
- HTML: Популярный самоучитель - Александр Чиртик - Программирование
- Как сдвинуть гору Фудзи? Подходы ведущих мировых компаний к поиску талантов - Паундстоун Уильям - Программирование
- C# для профессионалов. Том II - Симон Робинсон - Программирование