Presentation is loading. Please wait.

Presentation is loading. Please wait.

Списки типів Нікітін Олексій. Навіщо потрібні списки типів? Розглянемо шаблон Abstract Factory. class WidgetFactory { public: virtual Window* createWindow()

Similar presentations


Presentation on theme: "Списки типів Нікітін Олексій. Навіщо потрібні списки типів? Розглянемо шаблон Abstract Factory. class WidgetFactory { public: virtual Window* createWindow()"— Presentation transcript:

1 Списки типів Нікітін Олексій

2 Навіщо потрібні списки типів? Розглянемо шаблон Abstract Factory. class WidgetFactory { public: virtual Window* createWindow() = 0; virtual Button* createButton() = 0; virtual ScrollBar* createScrollBar() = 0; }

3 1) Така фабрика може створювати лише об’єкти типу Widget, Button, ScrollBar 2) Функціями-членами класу WidgetFactory неможливо вільно маніпулювати. Розглянемо такий код template T* makeRedWidget(WidgetFactory& factory) { T* pw = factory.createT();//неможливо pw->setColor(RED); return pw; }

4 Хотілося б мати Фабрику, якій можна вказати – які саме об’єкти вона повинна створювати. Наприклад typedef AbstractFactory WidgetFactory. Але шаблони не можуть мати змінну кількість параметрів.

5 template T* makeRedWidget(WidgetFactory& factory) { T* pw = factory.create (); pw->setColor(RED); return pw; } Але в С++ неможливо створити шаблонну віртуальну функцію.

6 Визначення списків типів Список, який складається з двох типів. template struct Typelist { typedef T head; typedef U tail; };

7 Список, який складається з трьох типів. typedef Typelist > Charlist; Також потрібен нульовий тип списку, який не містить жодного типу, нехай це буде класс NullType. Також нехай NullType буде маркером кінця списку.

8 Список, який містить один тип typedef Typelist OneTypeList; Два типи typedef Typelist > TwoTypeList;

9 За допомогою макросів можна покращити зовнішній вигляд визначення списків типів. #define TYPELIST_1(T1) Typelist #define TYPELIST_2(T1, T2) Typelist #define TYPELIST_3(T1, T2, T3) Typelist …..

10 Визначення списку з чотирьох типів typedef TYPELIST_4(char, short, int, long int) MyTypeList; еквівалентно Typelist<char, Typelist<short, Typelist<int, Typelist > > >

11 Обрахування дліни списку template struct Length; template <> struct Length { enum { value = 0 }; } template struct Length > { enum { value = 1 + Length ::value }; }

12 Індексований доступ template struct TypeAt; Надаємо список типів TList та index. Отримуємо оголошення типу, який стоїть в списку за певним індексом.

13 template struct TypeAt, 0> { typedef Head Result; } template struct TypeAt, i> { typedef typename TypeAt ::Result Result; };

14 Пошук індекса типа template struct IndexOf; template struct IndexOf { enum { value = -1; }; }

15 template struct IndexOf, T> { enum { value = 0 }; }; template struct IndexOf, T> { private: enum { temp = IndexOf ::value }; public: enum { value = (temp == -1 ? -1 : 1 + temp) }; };

16 Додавання елемента template struct Append; template <> struct Append { typedef NullType Result; }; template struct Append { typedef TYPELIST_1(T) Result; };

17 template struct Append > { typedef Typelist Result; } template struct Append, T> { typedef Typelist ::Result> Result; };

18 Видалення елемента template struct Erase; template struct Erase { typedef NullType Result; }

19 template struct Erase, T> { typedef Tail Result; //typedef typename EraseAll ::Result result; }; template struct Erase, T> { typedef Typelist<Head, typename Erase ::Result> Result; };

20 Видалення дублікатів template struct NoDuplicates; template <> struct NoDuplicates { typedef NullType Result; }; template struct NoDuplicates > { private: typedef typename NoDuplicates ::Result L1; typedef typename Erase ::Result L2; public: typedef Typelist Result; };

21 Заміна елемента template struct Replace; template struct Replace { typedef NullType Result; };

22 template struct Replace, T, U> { typedef Typelist Result; //typedef Typelist<U, typename Replace ::Result > Result; }; template struct Replace, T, U> { typedef Typelist<Head, typename Replace ::Result> Result; };

23 Частково впорядковані списки типів Потрібно в певному списку переставити типи так, щоб нащадки були попереду. Еквівалентно обходу ієрархії класів знизу уверх.

24 Потрібні: #define SUPERSUBCLASS(T, U) SuperSubclass ::value який має значення True, якщо класс U є нащадком класу T. Select – використовує отримане boolean значення. template struct Select { typedef T Result; }; template struct Select { typedef U Result; };

25 MostDerived Пошук нащадка самого нижнього рівня template struct MostDerived; template struct MostDerived { typedef T Result; };

26 template struct MostDerived, T> { private: typedef typename MostDerived ::Result Candidate; public: typedef typename Select <SUPERSUBCLASS(Candidate, Head), Head, Candidate>::Result Result; };

27 DerivedToFront template struct DerivedToFront; template<> struct DerivedToFront { typedef NullType Result; };

28 template struct DerivedToFront > { private: typedef typename MostDerived ::Result TheMostDerived; typedef typename Replace ::Result Temp; typedef typename DerivedToFront ::Result L; public: typedef Typelist Result; };

29 Генерація розподілених ієрархій template struct Unit { T value_; } template class Unit> class GenScatterHierarchy; Процес конкретизації класса GenScatterHierarchy закінчується спадкуванням класу Unit, конкретизованого кожним типом зі списку типів

30 typedef GenScatterHierarchy WidgetInfo; Порожній список: template class Unit> class GenScatterHierarchy { };

31 Атомарний тип ( не список типів) template class Unit> class GenScatterHierarchy : public Unit { typedef Unit LeftBase; };

32 Список типів: template class Unit> class GenScatterHierarchy, Unit> : public GenScatterHierarchy, public GenScatterHierarchy { public: typedef GenScatterHierarchy LeftBase; typedef GenScatterHierarchy RightBase; };

33

34 Звертання до атрибуту value_ класу Holder через екземпляр класу WidgetInfo. WidgetInfo obj; string name = (static_cast &>(obj)).value_;

35 Генерація лінійних ієрархій template class EventHandler { public: virtual void OnEvent(const T&, int eventId) = 0; virtual void ~EventHandler() { } };

36 typedef GenScatterHierarchy < TYPELIST_3(Window, Button, ScrollBar), EventHandler > WidgetEventHandler; Через множинне спадкування клас WidgetEventHandler містить три вказівника на віртуальні таблиці, по одній для кожної конкретизації класу EventHandler.

37 У випадку звичайного спадкування клас WidgetEventHandler може мати лише один вказівник на віртуальну таблицю

38 Рішення template < class TList, template class Unit, class Root = EmptyType > class GenLinearHierarchy;

39 template < class T1, class T2, template class Unit, class Root > class GenLinearHierarchy, Unit, Root> : public Unit > { };

40 template < class T, template class Unit, class Root > class GenLinearHierarchy : public Unit { };

41 Приклад використання template class EventHandler: public Base { public: virtual void OnEvent(T& obj, int eventId); }; typedef GenLinearHierarchy < TYPELIST_3(Window, Button, ScrollBar), EventHandler > MyEventHandler.

42

43 Дякую за увагу


Download ppt "Списки типів Нікітін Олексій. Навіщо потрібні списки типів? Розглянемо шаблон Abstract Factory. class WidgetFactory { public: virtual Window* createWindow()"

Similar presentations


Ads by Google