• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
General Functors
 

General Functors

on

  • 629 views

 

Statistics

Views

Total Views
629
Views on SlideShare
629
Embed Views
0

Actions

Likes
0
Downloads
1
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    General Functors                                                                                                                General Functors Presentation Transcript

    • Generalized FUNCTORS В рамках курсу “Актуальні проблеми програмної інженерії”, 2009 р. Лозинський Ігор, Фін-3
    • Ги-ги…
      • Додаткова інформація:
      • В презентації 32 сторінки
      • Наперед перепрошую за всі лажі та недопрацювання.
    • Майже гасло
      • “ Особливо розумні” технології призначені для досягнення простоти.
      • ( original : Clever techniques should be applied for the benefit of simplicity. )
    • Що воно таке?
      • Узагальнений функтор – це будь-який виклик процедури, що дозволений в С++ та інкапсульований в об'єкт першого класу, який гарантує типову безпеку
      • generalized functor is any processing invocation that C++ allows, encapsulated as a typesafe first-class object
    • Для чого?
      • Узагальнені функтори дозволяють зберігати виклики процедур у вигляді значень, передавати їх в якості параметрів, і виконувати іх далеко від місця створення. Суттєвою відмінністю між вказівниками на функції та узагальненими функторами в тому, що останні можуть зберігати стан об'єкта та викликати його методи.
    • The Command Design Pattern
      • Gamma, Erich, Richard Helm, Ralph Johnson, and John Vlissides . 1995. Design Patterns: Elements of Reusable Object-Oriented Software.
    • Що це дає?
      • Модуль, що здійснює виклик не тільки не знає як виконується робота, а й не має уявлення для якого виду роботи призначений клас Command
    • Застосування
      • // Resize the window
      • window.Resize(0, 0, 200, 100);
      • Command resizeCmd(
      • window, // Object
      • &Window::Resize, // Member function
      • 0, 0, 200, 100); // Arguments
      • // Later on...
      • resizeCmd.Execute(); // Resize the window
    • В реальному житті
      • Розробка інтерфейсів користувача окремо від самих програм ( skinnable )
      • Оболонки не мають архітектури, вони лише надають місця для об'єктів класу Command
    • Generalized callback
      • void Foo(); void Bar();
      • int main()
      • {
      • void (*pF)() = &Foo;
      • Foo(); // Call Foo directly
      • Bar(); // Call Bar directly
      • (*pF)(); // Call Foo via pF
      • void (*pF2)() = pF; // Create a copy of pF
      • pF = &Bar; // Change pF to point to Bar
      • (*pF)(); // Now call Bar via pF
      • (*pF2)(); // Call Foo via pF2
      • }
    • Ті, що підтримують operator() ( callable )
      • Функції
      • Вказівники на функції
      • Відсилки на функції (константні вказівники)
      • Функтори (об'єкти, в яких визначений operator() )
      • Результати застосування операторів .* та ->* до указників на функції-члени.
    • Скелет Functor ’ а
      • Клас Functor має поліморфну реалізацію, але це сховано всередині нього.
      • Реалізація базового класу - FunctorImpl
    • Починаємо реалізовувати
      • Перша реалізація – перша проблема
      • class Functor {
      • public: void operator ()();
      • // other member functions
      • private:
      • // implementation goes here
      • };
    • Виходить без шаблонів ніяк?
      • template < typename ResultType>
      • class Functor {
      • public:
      • ResultType operator ()();
      • // other member functions
      • private:
      • // implementation
      • };
    • Ну а де аргументи?
      • Ми не маємо морального права накладати обмеження на кількість аргументів operator() ’ а та на їх тип.
      • Крім того змінних шаблонів в С++ немає.
      • А еліпси ( ellipsis ) типу printf – це не красиво, та ще й небезпечно.
      • Що робити?
    • Так теж не годиться
      • // Functor with no arguments template
      • < typename ResultType>
      • class Functor { ... };
      • // Functor with one argument template
      • < typename ResultType, typename Parm1>
      • class Functor { ... };
    • Списки типів 
      • < typename ResultType, class TList>
      • class Functor { ... };
      • Functor <double, TYPELIST_2 (int, double)> m yFunctor;
    • Але й списки не ідеальні
      • template < typename R>
      • class FunctorImpl<R, NullType> {
      • public: virtual R operator() () = 0;
      • virtual FunctorImpl* Clone() const = 0;
      • virtual ~FunctorImpl() {}
      • };
      • template < typename R, typename P1>
      • class FunctorImpl<R, TYPELIST_1(P1)>{
      • public: virtual R operator() (P1) = 0;
      • virtual FunctorImpl* Clone() const = 0;
      • virtual ~FunctorImpl() {}
      • };
    • Сам пан Functor
      • template < typename R, class TList>
      • class Functor {
      • public:
      • Functor();
      • Functor( const Functor&);
      • Functor& operator=( const Functor&);
      • explicit Functor( std::auto_ptr <Impl> spImpl);
      • ...
      • private:
      • FunctorImpl<R, TList> Impl;
      • std::auto_ptr <Impl> spImpl_;
      • };
    • Маленька хитрість
      • template < typename R, class TList>
      • class Functor {
      • typedef TList ParmList;
      • typedef typename TypeAtNonStrict<TList, 0, EmptyType>::Result Parm1;
      • typedef typename TypeAtNonStrict<TList, 1, EmptyType>::Result Parm2;
      • ... as above ...
      • };
      • Доступаємось до типу, знаючи його номер (дивно, але працює  )
    • Реалізація operator() ’ а
      • template < typename R, class TList>
      • class Functor {
      • ... as above ...
      • public:
      • R operator() ()
      • { return (*spImpl_)(); }
      • R operator() (Parm1 p1)
      • { return (*spImpl_)(p1); }
      • R operator() (Parm1 p1, Parm2 p2)
      • { return (*spImpl_)(p1, p2); }
      • };
    • В чому фокус?
      • Functor<double, TYPELIST_2(int, double)> myFunctor;
      • double result = myFunctor(4, 5.6);
      • // Wrong invocation.
      • double result = myFunctor();
    • Робота з функторами
      • template < typename R, class TList>
      • class Functor {
      • ... as above ...
      • public :
      • template < class Fun>
      • Functor( const Fun& fun);
      • };
      • Таким чином ми доступатимемось до інших функторів
    • Так багато коду для одного конструктора
      • template < class ParentFunctor, typename Fun>
      • class FunctorHandler : public FunctorImpl
      • <
      • typename ParentFunctor::ResultType,
      • typename ParentFunctor::ParmList
      • >
      • {
      • public :
      • typedef typename ParentFunctor::ResultType ResultType;
    • … готуємо конструктор
      • FunctorHandler( const Fun& fun) : fun_(fun) {}
      • FunctorHandler* Clone() const {
      • return new FunctorHandler(*this); }
      • ResultType operator() () { return fun_(); }
      • ResultType operator() ( typename ParentFunctor::Parm1 p1) {
      • return fun_(p1); }
      • ResultType operator() ( typename ParentFunctor::Parm1 p1, typename ParentFunctor::Parm2 p2){
      • return fun_(p1, p2); }
      • private:
      • Fun fun_ ;
      • };
    • Нарешті вимучили наш конструктор
      • template < typename R, class TList>
      • template < typename Fun>
      • Functor<R, TList>::Functor( const Fun& fun) :
      • spImpl_( new FunctorHandler<Functor, Fun>(fun));
      • { }
      • Ще один трюк – шаблонне визначення члена поза межами класу
      • ( &quot;out-of-class member template definition.&quot; )
    • Тестуємо – все красиво
      • #include “ Functor.h ”
      • #include <iostream>
      • struct TestFunctor {
      • void operator() (int i, double d) {
      • cout <<&quot;TestFunctor::operator()(&quot; << i << &quot;, &quot; << d << &quot;) called. &quot;; }
      • };
      • int main() {
      • TestFunctor f;
      • Functor<void, TYPELIST_2(int, double)> cmd(f);
      • cmd(4, 4.5);
      • }
    • Не просто красиво – дуже красиво
      • Працюємо з функторами
      • Працюємо з функціями
      • Автоматично зводимо типи аргументів та результатів (все й справді чесно) (приклад: char* -> string )
    • Вказівники на методи об'єктів
      • Є певні нюанси (але вони дещо виходять за межі нашого обговорення, та й для чого ускладнювати?)
      • Реалізується тим же шляхом що й FunctorHandler
    • Бонуси
      • Зв'язування певних атрибутів (до початку виклику ми не тільки вкажемо на виконавця, але й задамо атрибути виконання, тобто певне описання середовища, в якому відбувається робота ).
      • Ланцюжок – ( MacroCommand , з Gamma et al* , 1995 ) - дозволяє створювати пакет виконання команд. Всі команди на момент “запаковування” повинні бути зв'язаними. Проте пізніше однією командою можна запустити цілу програму, створену на етапі виконання.
      • * Gamma, Erich, Richard Helm, Ralph Johnson, and John Vlissides . 1995. Design Patterns: Elements of Reusable Object-Oriented Software. Reading, MA: Addison-Wesley.
    • Де це знайти?
      • loki
      • Посилання:
      • http://sourceforge.net/projects/loki-lib
      • Для презентації використовувалась версія 0.1.7
    • Ніби кінець…
      • Спасибі за увагу
      • Буду вдячний, якщо питання Ви не задаватимете. 