1 / 28

C++ templates

C++ templates. Синтаксис. template < typename T > void f( const T& value) { std:: cout << "Value is: " << value << std:: endl ; } template < typename T, size_t n > struct Array { T data[n]; };. Примеры использования. template < typename T > class auto_ptr {

Download Presentation

C++ templates

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C++ templates

  2. Синтаксис template < typenameT > void f(const T& value) { std::cout << "Value is: " << value << std::endl; } template < typename T, size_t n > structArray { T data[n]; };

  3. Примеры использования template < typenameT > class auto_ptr { typedefauto_ptrMyType; T* _ptr; auto_ptr(const MyType& other); MyType& operator = (const MyType& other); public: auto_ptr(T* const ptr) : _ptr(ptr) { } ~auto_ptr() { delete _ptr; } T& operator *() const { return *_ptr; } T* operator ->() const { return _ptr; } };

  4. Примеры использования structA { inta; }; intmain() { auto_ptr<A> p_a = new A; (*p_a).a = 9; inti = p_a->a; return 0; }

  5. smart pointers • std::auto_ptr – лучше не использовать • _com_ptr_t – для COM-интерфейсов • boost::scoped_ptr – некопируемый • boost::shared_ptr – копируемый, использует подсчёт ссылок • boost::weak_ptr – решает проблему «кольцевых ссылок»

  6. boost:: scoped_ptr template<class T> class scoped_ptr// noncopyable { T * ptr; scoped_ptr(scoped_ptrconst &); // prohibited scoped_ptr & operator=(scoped_ptrconst &); // prohibited void operator==( scoped_ptrconst& ) const; // prohibited void operator!=( scoped_ptrconst& ) const; // prohibited public: explicit scoped_ptr(T * p = 0); // never throws explicit scoped_ptr(std::auto_ptr<T> p); // never throws ~scoped_ptr(); // never throws T & operator*() const; // never throws T * operator->() const; // never throws operator bool () const; // never throws bool operator! () const; // never throws T * get() const; // never throws void reset(T * p = 0); // never throws void swap(scoped_ptr & b); // never throws };

  7. std::auto_ptr template < class _Ty > class auto_ptr { public: template<class _Other> operator auto_ptr<_Other>() { return (auto_ptr<_Other>(*this)); } template<class _Other> auto_ptr<_Ty>& operator = (auto_ptr<_Other>& _Right) { reset(_Right.release()); return (*this); } template<class _Other> auto_ptr(auto_ptr<_Other>& _Right) : _Myptr(_Right.release()) {} _Ty *release() { _Ty *_Tmp = (_Ty *)_Myptr; _Myptr = 0; return (_Tmp); } ... };

  8. Недостатки глобальных переменных • Объекты создаются всегда, даже если они не используются • Порядок инициализации в общем случае неизвестен • Объекты не разрушаются до завершения программы • Проблемы с исключениями в конструкторах объектов

  9. Singleton template < typename T > class Singleton { public: static T& Instance() { static T instance; return instance; } static const T& ConstInstance() { return const_cast<const T&>(Instance()); } };

  10. Singleton class A { private: friend class Singleton<A>; A() {} public: inta; }; intmain() { Singleton<A>::Instance().a = 3; std::cout << Singleton<A>::ConstInstance().a << std::endl; return 0; }

  11. Частичная специализация шаблонов template < typename T > T MaxValue(); template < > int MaxValue<int>() { return INT_MAX; } template < > float MaxValue<float>() { return FLT_MAX; } int main() { std::cout << "Max int value = " << MaxValue<int>() << std::endl; std::cout << "Max float value = " << MaxValue<float>() << std::endl; return 0; }

  12. Compile time check template <boolb> structCompileTimeError; template <> structCompileTimeError<true>{}; CompileTimeError<2 == 4> ERROR_assert_failed; #define STATIC_CHECK(expr, msg) \ { CompileTimeError<expr> ERROR_##msg; (void)ERROR_##msg; } intmain() { STATIC_CHECK(2 == 5, assert_failed) return 0; }

  13. Шаблонные шаблонные параметры template < typenameT, template <typename> class Creator = NewCreator > class Singleton { public: typedefT* InstancePtr; private: static InstancePtr _instancePtr; static void Destroy(void) { if(_instancePtr != NULL) Creator<T>::Destroy(_instancePtr); } public: static T& Instance() { if(_instancePtr == NULL) { _instancePtr = Creator<T>::Create(); atexit(&Singleton::Destroy); } return *_instancePtr; } }; template < typenameT, template <typename> class C> typenameSingleton<T, C>::InstancePtr Singleton<T, C>::_instancePtr = NULL;

  14. Шаблонные шаблонные параметры template <class T> structMallocCreator { static T* Create() { void* p = std::malloc(sizeof(T)); if (!p) return 0; return new(p) T; } static void Destroy(T* p) { p->~T(); std::free(p); } }; template <class T> structNewCreator { static T* Create() { return new T; } static void Destroy(T* p) { delete p; } };

  15. Недостатки указателей на функции • Нет информации о типах аргументов и возвращаемого значения • Указатель на функцию необходимо перед вызовом проверять на NULL • Есть возможность привести указатель на функцию к любому указателю • Разный синтаксис вызова для указателей на функции и указателей на методы

  16. Функторы, простая реализация template < typenameSignature > class function; template < typenameR, typenameP > class function < R (P) > { typedeffunction MyType; typedefR (*Signature)(P); Signature _func; MyType& operator = (const MyType&); public: function(Signature func) : _func(func) { } function(const MyType& other): _func(other._func) { } R operator () (P p) { return _func(p); } };

  17. Функторы, простая реализация template <typenameObjType, typenameR, typenameP1, typenameP2> class function < R (ObjType::*) (P1, P2) > { typedeffunction MyType; typedefR (ObjType::*Signature)(P1, P2); Signature _func; MyType& operator = (const MyType&); public: function(Signature func) : _func(func) { } function(const MyType& other): _func(other._func) { } R operator () (ObjType& obj, P1 p1, P2 p2) { return (obj.*_func)(p1, p2); } };

  18. Функторы, простая реализация structA { char C; A(char c = ‘X') : C(c) { } void member_func(double i, boolb) { if (b) std::cout << C << i << std::endl; } }; intmain() { A a; function< void (A::*)(double, bool) > f(&A::member_func); f(a, 0.5, true); function < int (int) > f2(&abs); std::cout << f2(-123) << std::endl; return 0; }

  19. Функторы STL intmain() { A a; std::mem_fun1_t< void, A, double > f = std::mem_fun(&A::member_func); f(&a, 0.5); std::mem_fun1_ref_t < void, A, double > f_ref = std::mem_fun_ref(&A::member_func); f_ref(a, 0.7); std::pointer_to_unary_function<int, int> f2 = std::ptr_fun(&abs); std::cout << f2(-123) << std::endl; return 0; }

  20. Недостатки функторов STL • Уродливый синтаксис • Отсутствие функторов с большим количеством параметров • Отсутствует возможность инициализации функтора с сигнатурой func1 указателем на func2: struct B : public A{}; void func1(B*); void func2(A*);

  21. boost::function intmain() { A a; boost::function < void (A&, double) > f = &A::member_func; f(a, 0.5); boost::function < int (int) > f2 = &abs; std::cout << f2(-123) << std::endl; return 0; }

  22. Применение функторов void generate_int(int& i) { i = rand() % 100 - 50; } void print_int(inti) { std::cout << i << " "; } intmain() { std::vector<int> vec(10); std::for_each(vec.begin(), vec.end(), &generate_int); std::for_each(vec.begin(), vec.end(), &print_int); std::cout << std::endl; std::vector<int> out_vec; std::transform(vec.begin(), vec.end(), std::back_inserter(out_vec), &abs); std::for_each(out_vec.begin(), out_vec.end(), &print_int); std::cout << std::endl; return 0; }

  23. Привязывание параметров intmain() { std::vector<int> vec(10); std::for_each(vec.begin(), vec.end(), &generate_int); std::for_each(vec.begin(), vec.end(), &print_int); std::cout << std::endl; vec.erase( std::remove_if(vec.begin(), vec.end(), std::bind1st(std::less<int>(), 10)), vec.end() ); std::for_each(vec.begin(), vec.end(), &print_int); std::cout << std::endl; return 0; }

  24. Недостатки std::bind1st/2nd • Работают только для binary_function • Привязывают только один аргумент • Неудобный синтаксис • Нет возможности привязать ссылку: void inc (int& n, bool) { ++n; } // ... std::bind1st(std::ptr_fun(&inc), i) (true);

  25. boost::bind boolin_range( intmin_val, intmax_val, intval ) { return (val >= min_val) && (val <= max_val); } intmain() { // ... boost::function < bool(int) > pred = boost::bind(&in_range, 5, 15, _1); vec.erase( std::remove_if(vec.begin(), vec.end(), pred), vec.end() ); // ... return 0; }

  26. “Подводные камни”boost::bind class WindowBase { typedefboost::function < void (void) > EventHandler; EventHandler _onPaint; protected: WindowBase(const EventHandler& onPaint) : _onPaint(onPaint) { } // ... }; structMyWindow : public WindowBase { MyWindow() : WindowBase(boost::bind(&MyWindow::OnPaint, this)) { } void OnPaint() { } }; MyWindowCreateMyGreatWindow() { return MyWindow(); } intmain() { MyWindowwnd = CreateMyGreatWindow(); return 0; }

  27. Преимущества использования шаблонов C++ • Шаблоны решают проблему дублирования кода • Зачастую шаблоны позволяют избавиться от динамической диспечеризации и повысить скорость работы приложения • Позволяют отследить большую часть ошибок на этапе компиляции • Использование стратегий позволяет не писать сложные классы с нуля, а собирать их из множества меньших • Можно грабить корованы

  28. Список литературы • Бьерн Страуструп. Язык программирования С++ • Скотт Мейерс. Эффективное использование С++ • Скотт Мейерс. Наиболее эффективное использование С++ • Скотт Мейерс. Эффективное использование STL • Герб Саттер. Решение сложных задач на C++ • Герб Саттер. Новые сложные задачи на C++ • Андрей Александреску. Современное проектирование на C++ • Герб Саттер. Андрей Александреску. Стандарты программирования на С++. 101 правило и рекомендация • Владимир Сорокин. Голубое сало.

More Related