'

C++ templates

Понравилась презентация – покажи это...





Слайд 0

C++ templates


Слайд 1

Синтаксис 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]; };


Слайд 2

Примеры использования template < typename T > class auto_ptr { typedef auto_ptr MyType; 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; } };


Слайд 3

Примеры использования struct A { int a; }; int main() { auto_ptr<A> p_a = new A; (*p_a).a = 9; int i = p_a->a; return 0; }


Слайд 4

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


Слайд 5

boost:: scoped_ptr template<class T> class scoped_ptr // noncopyable { T * ptr; scoped_ptr(scoped_ptr const &); // prohibited scoped_ptr & operator=(scoped_ptr const &); // prohibited void operator==( scoped_ptr const& ) const; // prohibited void operator!=( scoped_ptr const& ) 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 };


Слайд 6

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); } ... };


Слайд 7

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


Слайд 8

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()); } };


Слайд 9

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


Слайд 10

Частичная специализация шаблонов 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; }


Слайд 11

Compile time check template <bool b> struct CompileTimeError; template <> struct CompileTimeError<true>{}; CompileTimeError<2 == 4> ERROR_assert_failed; #define STATIC_CHECK(expr, msg) \ { CompileTimeError<expr> ERROR_##msg; (void)ERROR_##msg; } int main() { STATIC_CHECK(2 == 5, assert_failed) return 0; }


Слайд 12

Шаблонные шаблонные параметры template < typename T, template <typename> class Creator = NewCreator > class Singleton { public: typedef T* 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 < typename T, template <typename> class C> typename Singleton<T, C>::InstancePtr Singleton<T, C>::_instancePtr = NULL;


Слайд 13

Шаблонные шаблонные параметры template <class T> struct MallocCreator { 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> struct NewCreator { static T* Create() { return new T; } static void Destroy(T* p) { delete p; } };


Слайд 14

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


Слайд 15

Функторы, простая реализация template < typename Signature > class function; template < typename R, typename P > class function < R (P) > { typedef function MyType; typedef R (*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); } };


Слайд 16

Функторы, простая реализация template <typename ObjType, typename R, typename P1, typename P2> class function < R (ObjType::*) (P1, P2) > { typedef function MyType; typedef R (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); } };


Слайд 17

Функторы, простая реализация struct A { char C; A(char c = ‘X') : C(c) { } void member_func(double i, bool b) { if (b) std::cout << C << i << std::endl; } }; int main() { 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; }


Слайд 18

Функторы STL int main() { 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; }


Слайд 19

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


Слайд 20

boost::function int main() { 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; }


Слайд 21

Применение функторов void generate_int(int& i) { i = rand() % 100 - 50; } void print_int(int i) { std::cout << i << " "; } int main() { 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; }


Слайд 22

Привязывание параметров int main() { 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; }


Слайд 23

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


Слайд 24

boost::bind bool in_range( int min_val, int max_val, int val ) { return (val >= min_val) && (val <= max_val); } int main() { // ... 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; }


Слайд 25

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


Слайд 26

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


Слайд 27

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


×

HTML:





Ссылка: