Быстрые делегаты C++
ОГЛАВЛЕНИЕ
Введение
Дон Клагстон хорошо описал указатель функции-члена и его поведение в статье: "Указатели функции-члена и наиболее быстрые делегаты C++". Вкратце, указатели функции-члена не могут быть присвоены указателю данных void *, поэтому нужно осторожно обращаться с указателем функции-члена как с данные (функтор). FastestDelegate Дона – это самый быстрый делегат, как он утверждает, но он использовал reinterpret_cast<>, чтобы обмануть компилятор, что он назвал 'хитрым трюком' в своей статье.
Позже Сергей Рязанов представил быстрый делегат C++, который он считал таким же быстрым, как и FastestDelegate Дона, но полностью совместимым со стандартами C++. Его метод состоит в использовании шаблонизированной статической функции-члена ('заглушки'), чтобы сохранять/восстанавливать информацию о вызове функции (возвращаемый тип, тип аргумента, cv-спецификатор и зависящее от платформы соглашение о вызове) во время компиляции. В реальности это не является чем-то новым, поскольку аналогичный подход уже был представлен Ричем Хикеем в его статье "Обратные вызовы в C++ с не-типовой параметр шаблона. К сожалению, не многие доступные для приобретения компиляторы поддерживают эту стандартную возможность C++. Поэтому его код в некотором смысле не является переносимым. использованием шаблонов-функторов", 1994. Рич называл такую статическую функцию-член функцией 'переходником'. Тем не менее, метод Сергея уникален, так как он передает информацию о вызове члена-функции через
Есть еще одна отличная статья о том, как реализовать делегаты C++: "Еще одна реализация обобщенных функторов на C++", автор Алексей Трунов. Он объясняет и всесторонне анализирует требования обобщенных функторов и проблемы существующих делегатов.
Кстати, эти рассматриваются как 'быстрые', так как они могут избежать выделения памяти кучи для хранения указателей членов-функций, в отличие от boost::function.
Очередной быстрый делегат C++ - что нового в нем?
В нашем быстром делегате нет ничего нового. Все возможности, показанные в этой статье, уже существуют в других реализациях.
- Быстрый делегат. (В большинстве случаев не используется выделение памяти кучи.)
- Поддерживает три вызываемых объекта (свободная функция, функция-член и функтор).
- Совместимы со стандартами C++, поэтому портативны (проверены в VC6, VC71, и DEV-C++ 4.9.9.2 (Mingw/gcc 3.4.2)).
- Совместимы со стандартной библиотекой шаблонов (STL), подходят для конструирования копий и способны присваиваться.
- Равенство, меньше чем, и больше чем объекты сравнения.
- Правильность Cv-спецификатора (const).
- Поддержка зависящих от платформы соглашений о вызове (__stdcall, __fastcall, __cdecl).
- Предпочтительный синтаксис, переносимый синтаксис, или даже смешанный.
- Смягчение проверки соответствия типов.
- static_assert во время компиляции.
- Сохраняет только указатель (ссылку) на связанный объект или копирует связанный объект внутри. (новое)
- Сохраняет интеллектуальный указатель на связанный объект внутри. (новое)
- Пользовательский распределитель памяти. (новое)
- Настройка поведения/функций делегата путем указания соответствующих макроопределений.
Но что если все эти возможности доступны в одном делегате? Не звучит ли это многообещающе? Давайте посмотрим!