Читаем Вариации на тему STL. Адаптер обобщенного указателя на функцию-член класса полностью

template

struct gen_mem_fun_t {

 explicit gen_mem_fun_t(R (T::*pm_)()): pm(pm_) {}

 template R operator()(TT p) {return (p.operator->()->*pm)();}

private:

 R (T::*pm)();

};

Правда, возникает другая одна проблема – если теперь мы захотим использовать наш адаптер с обычным указателем, то потерпим поражение: обычные указатели не понимают operator->(). Таким образом, нам необходимо специализировать нашу функцию operator() для работы с обычными указателями:

template<>

R operator()(T* p) {

 return (p->*pm)();

}

Реализация gen_mem_fun

Теперь реализация gen_mem_fun становится тривиальной:

template

gen_mem_fun_t gen_mem_fun(R (T::*pm)()) {

 return gen_mem_fun_t(pm);

}

Проблемы с разными компиляторами

Специализация шаблонных функций – членов шаблонного класса

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

ПРИМЕЧАНИЕ К таким относятся, например, gcc-2.95 и gcc-2.96

Попробуем обойтись без них. Специализация в той или иной форме нам в любом случае понадобится, так что воспользуемся тем, что есть – частичной специализацией классов. Введем вспомогательный класс и специализируем его для особого случая обычных указателей.

template

struct gen_mem_fun_operator {

 R operator()(TT p, R (T::*pm)()) {return (p.operator->()->*pm)();}

};


template

struct gen_mem_fun_operator {

 R operator()(T* p, R (T::*pm)()) {return (p->*pm)();}

};


Тогда наш gen_mem_fun_t запишется так:

template

struct gen_mem_fun_t {

 explicit gen_mem_fun_t(R (T::*pm_)()): pm(pm_) {}

 template R operator()(TT p) {return gen_mem_fun_operator()(p, pm);}

private:

 R (T::*pm)();

};

Проблема “return void”

Посмотрим внимательнее на реализацию функции operator() в нашем адаптере. Что будет, если мы захотим в качестве типа возвращаемого значения функции использовать void? Наша функция запишется так: void operator() {return void;}. С точки зрения стандарта все хорошо, но все в нашем мире определяется стандартом: есть компиляторы, которые не воспринимают такую конструкцию как допустимую.

ПРИМЕЧАНИЕ

Таков, к примеру, Microsoft Visual C++ 6.0/7.0

К счастью, на помощь нам опять приходит частичная специализация:

template

struct gen_mem_fun_operator {

 void operator()(TT p, void (T::*pm)()) {(p.operator->()->*pm)();}

};


template

struct gen_mem_fun_operator {

 void operator()(T* p, void (T::*pm)()) {(p->*pm)();}

};

Частичная специализация

К сожалению, не все компиляторы поддерживают частичную специализацию шаблонных классов.

ПРИМЕЧАНИЕ К таким относится и Microsoft Visual C++ 6.0/7.0

Для решения этой проблемы можно использовать паттерн «traits», специфичный для C++. К сожалению, он не сможет помочь в случае, когда один из параметров шаблона специализируется типом, зависящим от другого параметра шаблона, но в случае проблемы «return void» он помочь сможет.

ПРИМЕЧАНИЕ

Вопрос, реально ли вообще симулировать частичную специализацию шаблонов, где специализируемый параметр шаблона зависит от неспециализируемого, на компиляторе, не поддерживающем частичную специализацию шаблонов и поддерживающем специализацию вообще только для глобальных классов и функций, остается открытым. Я такой возможности не вижу. Таким образом, создать без помощи препроцессора код нашего адаптера, компилирующийся и под gcc и под Visual C++, не представляется возможным.

Введем вспомогательный класс

template

struct gen_mem_fun_traits {

 template

 struct signature {

  typedef gen_mem_fun_base_t base;

 };

};


template<> struct gen_mem_fun_traits {

 template struct signature {

  typedef void_gen_mem_fun_base_t base;

 };

};


Этот класс специализирован для специального случая функции, возвращающей void. Таким образом, хоть нам и придется ввести дополнительный класс для функций, возвращающих void, для клиента это будет выглядеть единообразно: gen_mem_fun_traits::signature::base.

Перейти на страницу:

Похожие книги

C# 4.0: полное руководство
C# 4.0: полное руководство

В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки. Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию

Герберт Шилдт

Программирование, программы, базы данных
C++
C++

С++ – это универсальный язык программирования, задуманный так, чтобы сделать программирование более приятным для серьезного программиста. За исключением второстепенных деталей С++ является надмножеством языка программирования C. Помимо возможностей, которые дает C, С++ предоставляет гибкие и эффективные средства определения новых типов. Используя определения новых типов, точно отвечающих концепциям приложения, программист может разделять разрабатываемую программу на легко поддающиеся контролю части. Такой метод построения программ часто называют абстракцией данных. Информация о типах содержится в некоторых объектах типов, определенных пользователем. Такие объекты просты и надежны в использовании в тех ситуациях, когда их тип нельзя установить на стадии компиляции. Программирование с применением таких объектов часто называют объектно-ориентированным. При правильном использовании этот метод дает более короткие, проще понимаемые и легче контролируемые программы. Ключевым понятием С++ является класс. Класс – это тип, определяемый пользователем. Классы обеспечивают сокрытие данных, гарантированную инициализацию данных, неявное преобразование типов для типов, определенных пользователем, динамическое задание типа, контролируемое пользователем управление памятью и механизмы перегрузки операций. С++ предоставляет гораздо лучшие, чем в C, средства выражения модульности программы и проверки типов. В языке есть также усовершенствования, не связанные непосредственно с классами, включающие в себя символические константы, inline-подстановку функций, параметры функции по умолчанию, перегруженные имена функций, операции управления свободной памятью и ссылочный тип. В С++ сохранены возможности языка C по работе с основными объектами аппаратного обеспечения (биты, байты, слова, адреса и т.п.). Это позволяет весьма эффективно реализовывать типы, определяемые пользователем. С++ и его стандартные библиотеки спроектированы так, чтобы обеспечивать переносимость. Имеющаяся на текущий момент реализация языка будет идти в большинстве систем, поддерживающих C. Из С++ программ можно использовать C библиотеки, и с С++ можно использовать большую часть инструментальных средств, поддерживающих программирование на C. Эта книга предназначена главным образом для того, чтобы помочь серьезным программистам изучить язык и применять его в нетривиальных проектах. В ней дано полное описание С++, много примеров и еще больше фрагментов программ.

Бьёрн Страуструп , Бьярн Страустрап , Мюррей Хилл

Программирование, программы, базы данных / Программирование / Книги по IT
3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

Программирование, программы, базы данных / Программное обеспечение / Книги по IT