Lecture 2 Polymorphism, Traits, Policies, and Inheritance

Similar documents
Part X. Advanced C ++

boost::enable_if Deep Down Boostimagical Fun Christian Bay and Kasper A Andersen Department of Computer Science University of Copenhagen

Part III. Advanced C ++

Advanced C++ 4/13/2017. The user. Types of users. Const correctness. Const declaration. This pointer and const.

CS93SI Handout 04 Spring 2006 Apr Review Answers

use static size for this buffer

COEN244: Class & function templates

Templates. Zoltán Porkoláb: C++11/14 1

C++ Template Meta. A basic introduction to basic C++ techniques used in template metaprogramming.

Generic Programming in C++: A modest example

C++1z: Concepts-Lite !!! !!! !!!! Advanced Developer Conference C slides:

Object-Oriented Programming for Scientific Computing

CSCI-1200 Data Structures Fall 2018 Lecture 22 Hash Tables, part 2 & Priority Queues, part 1

Iterator Facade. Table of Contents. Overview. Usage. Iterator Core Access operator[] operator-> Reference

C++17 and Beyond. Mark Isaacson

STRICT_VARIANT. A simpler variant in C++ Chris Beck

What will happen if we try to compile, link and run this program? Do you have any comments to the code?

C++14 Reflections Without Macros, Markup nor External Tooling

C++ Basics. Data Processing Course, I. Hrivnacova, IPN Orsay

Object-Oriented Programming for Scientific Computing

Overload Resolution. Ansel Sermersheim & Barbara Geller Amsterdam C++ Group March 2019

QUIZ. What is wrong with this code that uses default arguments?

Mixin and CRTP in C++98/11. Zoltán Porkoláb, PhD.

C++ Modern and Lucid C++ for Professional Programmers

Table of Contents. Overview. Usage. Iterator Core Access. operator[] operator-> Reference

Type Erasure. Nevin :-) Liber Friday, October 29, Chicago C/C++ Users Group Nevin J. Liber All Rights Reserved.

eingebetteter Systeme

Overload Resolution. Ansel Sermersheim & Barbara Geller ACCU / C++ June 2018

6.096 Introduction to C++ January (IAP) 2009

Chapter 16 Templates and Inheritance

template <typename T> // unless it s an unqualified pointer struct IsPtr<T *> { enum { r = true }; };

Object-Oriented Programming for Scientific Computing

Contract Programming For C++0x

Using Enum Structs as Bitfields

Introduction to C++ Systems Programming

COMP6771 Advanced C++ Programming

Fast Introduction to Object Oriented Programming and C++

An Introduction to Template Metaprogramming

A brief introduction to C programming for Java programmers

Design Patterns in C++

COMP322 - Introduction to C++ Lecture 02 - Basics of C++

Design Patterns in C++

C++ For Science and Engineering Lecture 15

A Proposal to Add a Logical Const Wrapper to the Standard Library Technical Report

A Proposal to Add a Const-Propagating Wrapper to the Standard Library

C++ Modern and Lucid C++ for Professional Programmers

CS 251 INTERMEDIATE SOFTWARE DESIGN SPRING C ++ Basics Review part 2 Auto pointer, templates, STL algorithms

Instantiation of Template class

CE221 Programming in C++ Part 1 Introduction

GCC : From 2.95 to 3.2

Item 4: Extensible Templates: Via Inheritance or Traits?

Variables. Data Types.

Structuur van Computerprogramma s 2

September 19,

C++ Modern and Lucid C++ for Professional Programmers

Tokens, Expressions and Control Structures

1/29/2011 AUTO POINTER (AUTO_PTR) INTERMEDIATE SOFTWARE DESIGN SPRING delete ptr might not happen memory leak!

Expansion statements. Version history. Introduction. Basic usage

Pairing off iterators

C++ Coding Standards and Practices. Tim Beaudet March 23rd 2015

Introduction to C++ Professor Hugh C. Lauer CS-2303, System Programming Concepts

Polymorphism. Programming in C++ A problem of reuse. Swapping arguments. Session 4 - Genericity, Containers. Code that works for many types.

CSCI-1200 Data Structures Spring 2018 Lecture 14 Associative Containers (Maps), Part 1 (and Problem Solving Too)

Advanced C++ Topics. Alexander Warg, 2017

Advanced Systems Programming

Short Notes of CS201

Function Templates. Consider the following function:

Modern and Lucid C++ Advanced for Professional Programmers. Part 12 Advanced Library Design. Department I - C Plus Plus Advanced

GridKa School 2013: Effective Analysis C++ Templates

C++11: 10 Features You Should be Using. Gordon R&D Runtime Engineer Codeplay Software Ltd.

Function Composition and Return Type Deduction. Anthony Williams. 28th February Abstract

CS201 - Introduction to Programming Glossary By

Templates Templates are functions or classes that are parameterized. We have already seen a few in STL:

CS 247: Software Engineering Principles. C++ Templates. Reading: Eckel, Vol. 2 Ch. 5 Templates in Depth. U Waterloo CS247 (Spring 2017) p.

MODERN AND LUCID C++ ADVANCED

Agenda. The main body and cout. Fundamental data types. Declarations and definitions. Control structures

Laboratorio di Tecnologie dell'informazione

Debug C++ Without Running. Anastasia Kazakova

CS

G Programming Languages Spring 2010 Lecture 11. Robert Soulé, New York University

Part XI. Algorithms and Templates. Philip Blakely (LSC) C++ Introduction 314 / 370

CSCI-1200 Data Structures Fall 2017 Lecture 23 Functors & Hash Tables, part II

The following is an excerpt from Scott Meyers new book, Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs.

COMP6771 Advanced C++ Programming

C++ Programming: Polymorphism

Financial computing with C++

Introduction to GIL, Boost and Generic Programming

G Programming Languages Spring 2010 Lecture 8. Robert Grimm, New York University

COMP6771 Advanced C++ Programming

Function Binding. Special thanks to: John Edwards. Randy Gaul

CSE100. Advanced Data Structures. Lecture 4. (Based on Paul Kube course materials)

C++ Important Questions with Answers

Cpt S 122 Data Structures. Course Review Midterm Exam # 2

Pointers in C/C++ 1 Memory Addresses 2

Chapter 15 - C++ As A "Better C"

An introduction to. Templates. Generic Programming. Good old C. Metaprogramming 4/13/2017

Polymorphism. Contents. Assignment to Derived Class Object. Assignment to Base Class Object

Appendix. Grammar. A.1 Introduction. A.2 Keywords. There is no worse danger for a teacher than to teach words instead of things.

CORBA Programming with TAOX11. The C++11 CORBA Implementation

Lecture 4a Using The Standard Template Library. Jack Applin, Guest Lecturer

Transcription:

Lecture 2 Polymorphism, Traits, Policies, and Inheritance Kenny Erleben Department of Computer Science University of Copenhagen c K. Erleben, May 4, 2006 p. 1/36

Polymorphism 1 Traditional, define abstract base class class Geometry virtual std::string get_type() const = 0; virtual int number() const = 0; ; Note: Common behavior in base classes c K. Erleben, May 4, 2006 p. 2/36

Polymorphism 2 Now make derived classes and class Sphere : public Geometry virtual std::string get_type() const return "sphere"; virtual int number() return 1; ; class Box : public Geometry virtual std::string get_type() const return "box"; virtual int number() return 2; ; and so on... (Question: why virtuals?) c K. Erleben, May 4, 2006 p. 3/36

Polymorphism 3 Let us define some functions that work on different geometries void pair_test(geometry const * A,Geometry const * B) std::cout << "testing" << A->get_type() << " and " << B->get_type() << std::endl; Or a little more exotic void collision(std::vector<geometry *> const & geometries) for(unsigned i=0;i< geometries.size();++i) for(unsigned j=i+1;j< geometries.size();++j) pair_test(geometries[i],geometries[j]); c K. Erleben, May 4, 2006 p. 4/36

Polymorphism 4 Let us try our example functions int main() Sphere s0,s1; Box b0,b1,b2; pair_test(b2,s1); std::vector<geometry*> geometries; geometries.push_back(&s0); geometries.push_back(&b0); geometries.push_back(&s1); geometries.push_back(&b1); geometries.push_back(&b2); collision(geometries); c K. Erleben, May 4, 2006 p. 5/36

Polymorphism 5 Observe Interface is bounded Binding of interfaces is done at run-time (dynamically) Easy to create heterogeneous containers This is called Dynamic Polymorphism Consider the following tasks What if we want to extend with a new geometry type? class Prism : public Geometry... What if we want to extend with a method? virtual bool foo() const = 0; c K. Erleben, May 4, 2006 p. 6/36

Polymorphism 6 Let us try to use templates instead, no inheritance and class Sphere std::string get_type() const return "sphere"; int number() return 1; ; class Box std::string get_type() const return "box"; int number() return 2; ; c K. Erleben, May 4, 2006 p. 7/36

Polymorphism 7 We also need to rewrite our test function template<typename Geometry1, typename Geometry2> void pair_test(geometry1 const & A,Geometry2 const & B) std::cout << "testing" << A.get_type() << " and " << B.get_type() << std::endl; and we can now use it int main()... pair_test(b0,s1);... pair_test(b2,s2); c K. Erleben, May 4, 2006 p. 8/36

Polymorphism 8 What about? void collision(std::vector<geometry *> const & geometries) for(unsigned i=0;i< geometries.size();++i) for(unsigned j=i+1;j< geometries.size();++j) pair_test(geometries[i],geometries[j]); Answer Sorry, this is impossible, we cannot handle std::vector<geometry *> const & geometries c K. Erleben, May 4, 2006 p. 9/36

Polymorphism 9 Observe Interface is unbounded Binding of interfaces is done at compile-time (statically) Cannot create heterogeneous containers This is called Static Polymorphism Consider the following tasks What if we want to extend with a new geometry type? class Prism What if we want to extend with a method? bool foo() const... ; c K. Erleben, May 4, 2006 p. 10/36

Pimpl 1 Or the bridge pattern, idea is to switch between implementations of an interface class Implementation virtual void doit() const = 0; ; Now class Interface protected: Implementation * m_body; void doit() m_body->doit() c K. Erleben, May 4, 2006 p. 11/36

Pimpl 2 And we can have class ImplA : public Implementaion void doit()... and class ImplB : public Implementation void doit()... If we know type at compile time then we can make a static version c K. Erleben, May 4, 2006 p. 12/36

Pimpl 3 template<typename Implementation> class Interface protected: Implementation m_body; void doit() m_body.doit() Advantages More type safety No pointers (See Boost Library 1) Should be faster! But we cannot swap implementation at run-time. c K. Erleben, May 4, 2006 p. 13/36

Fixed Traits 1 Let us study the example template<typename T> T accumulate( T * const begin, T * const end) T total = T(); while(begin!=end) total += *begin++; return totral; Problem One solution The return type T may have in-sufficient range to store the result value Imagine adding 1000 values of char, is this result likely to be in range 0..255? Fixed Traits c K. Erleben, May 4, 2006 p. 14/36

Fixed Traits 2 Using partial specialization, we define results type template<typename T> class acummulation_traits; template<> class acummulation_traits<char> typedef int result_type; ;... template<> class acummulation_traits<unsigned int> typedef unsigned long result_type; ; This way we can define as many result types as we please. c K. Erleben, May 4, 2006 p. 15/36

Fixed Traits 3 Now we use the new traits template<typename T> typename accumulation_traits<t>::result_type accumulate(t * const begin, T*const end) typedef typename accumulation_traits<t>::result_type result_type; result_type total = result_type(); while(begin!=end) total += *begin++; return total; This is called fixed traits, because it depends only on T, i.e. the caller cannot make a user-specified trait (this is called parameterized traits, more on this later). This is very generic, if you have an user-defined data-type class MyBigNumber then just create a specialization. c K. Erleben, May 4, 2006 p. 16/36

Fixed Traits 4 For instance somewhere in my_big_number.h (or another place) one writes class MyBigNumber.. ;... template<> class accumulation_traits<mybignumber> typedef MyInfinitelyBigNumber result_type; ; That s it. c K. Erleben, May 4, 2006 p. 17/36

Fixed Traits Example As an example let us look at a general iterator implementation using STL template<typename iterator_type> typename std::iterator_traits<iterator_type>::value_type accumulate(iter begin,iter end) typedef typename std::iterator_traits<iterator_type>::value_type value_ty value_type total = value_type(); while(...)... return total; This supports both pointers and STL iterators. c K. Erleben, May 4, 2006 p. 18/36

Value Traits 1 What if default constructor isn t zero? template<> class accumulation_traits<this_type> typedef that_type result_type; static result_type const zero = 0; ; Cool then we can write result_type total = accumulation_traits<t>::zero; So traits can be used to define type dependent constants. c K. Erleben, May 4, 2006 p. 19/36

Value Traits 2 One problem not all types (non-integral types) of static members can be initialized in header, we need a source file (Yrk!) that_type const accumulation_traits<this_type>::zero = 0; Another more interesting idea is to use static methods, template<> class accumulation_traits<this_type> typedef that_type result_type; static result_type zero() return 0 ; Cool, header-only implementation. c K. Erleben, May 4, 2006 p. 20/36

Parameterized Traits 1 Say we want to change the accumulation traits. We rewrite into a class implementation template< typename T, typename traits = accumulation_traits<t> > class Accumulation typename accumulation_traits<t>::result_type operator()(t * const begin, T*const end) typedef typename accumulation_traits<t>::result_type result_type; result_type total = result_type(); while(begin!=end) total += *begin++; return total; Oups, did you see the difference from the text-book? Non-static member We use operator() This is called a functor (more about than later in course) c K. Erleben, May 4, 2006 p. 21/36

Parameterized Traits 2 Note the default template parameter value, this is why we need a class-implementation (template functions cannot have default values, YET) template< typename T, typename traits = accumulation_traits<t> > class Accumulation typename accumulation_traits<t>::result_type operator()(t * const begin, T*const end) typedef typename accumulation_traits<t>::result_type result_type; result_type total = result_type(); while(begin!=end) total += *begin++; return total; c K. Erleben, May 4, 2006 p. 22/36

Parameterized Traits 3 One drawback, when we use it there is no template argument deduction, so we have to explicitly write Accumulation<char>()(&p[0],&p[100]); This looks ugly so we create some convenience functions template<typename T> typename accumulation_traits<t>::result_type accumulate( T * const...) return Accumulation<T>()(&p[0],&p[100]); c K. Erleben, May 4, 2006 p. 23/36

Parameterized Traits 4 And/or template<typename traits, typename T> typename traits::result_type accumulate( T * const...) return Accumulation<T,traits>()(&p[0],&p[100]); That is it. Sometimes it is good practice to hide the class definition in a namespace to avoid namespace pollution. c K. Erleben, May 4, 2006 p. 24/36

Policies 1 One way to look at a policy A policy can be used to define some user-specified behavior or action As an example template< typename T, typename Policy = SumPolicy, typename traits = accumulation_traits<t> > class Accumulation typename accumulation_traits<t>::result_type operator()(t * const begin, T*const end) typedef typename accumulation_traits<t>::result_type result_type; result_type total = result_type(); while(begin!=end) Policy::accumulate(total, *begin++ ); return total; Now we can control how accumulation is done c K. Erleben, May 4, 2006 p. 25/36

Policies 2 Say we want class SumPolicy template<typename T1,typename T2> static void accumulate(t1 & total, T2 const & val) total += val; Or class MultPolicy template<typename T1,typename T2> static void accumulate(t1 & total, T2 const & val) total *= val; Whatever we please, note We control the semantics It works as long as syntax is okay c K. Erleben, May 4, 2006 p. 26/36

Policies 3 Policies could be implemented differently, like template< typename T, typename Policy = SumPolicy, typename traits = accumulation_traits<t> > class Accumulation : public Policy typename accumulation_traits<t>::result_type operator()(t * const begin, T*const end) typedef typename accumulation_traits<t>::result_type result_type; result_type total = result_type(); while(begin!=end) accumulate(total, *begin++ ); return total; c K. Erleben, May 4, 2006 p. 27/36

Policies 4 Now one could have written class SumPolicy template<typename T1,typename T2> void accumulate(t1 & total, T2 const & val) total += val; c K. Erleben, May 4, 2006 p. 28/36

CRTP 1 The Curiously Recurring Template Pattern, well you do it like this template<typename child_type> class Base... ; template<typename T,...> class Child : public Base< Child<T> >... ; c K. Erleben, May 4, 2006 p. 29/36

CRTP 2 This can be useful for defining common interfaces without using an abstract base class, template<typename child_type> class Base void foo() child_type & self = static_cast<child_type&> ( *this ); self.foo(); bool goo(int cnt) const child_type const & self = static_cast<child_type const &> ( *this ); return self.goo(cnt); ; Now the compiler makes sure that class Child implements foo and goo. Great for implementing concepts (facades), see Boost iterator library. c K. Erleben, May 4, 2006 p. 30/36

CRTP 3 Not quite what happens if template<typename child_type> class Base void foo() child_type & self = static_cast<child_type&> ( *this ); self.foo(); ; class Derived : public Base<Derived> ; An infinite loop! Oh but shouldn t the compiler tell us that we forgot to implement foo on Derived? c K. Erleben, May 4, 2006 p. 31/36

CRTP 4 Work around 1: Private Solution class Derived : private Base<Derived> ; Work around 2: No name clash solution template<typename child_type> class Base void foo() child_type & self = static_cast<child_type&>(*this); self.goo(); ; c K. Erleben, May 4, 2006 p. 32/36

CRTP 5 Another example template<typename child_type> class ObjectCounter private: static unsigned int m_count = 0; protected: ObjectCounter()++m_count; ObjectCounter()--m_count; ObjectCounter(ObjectCounter<child_type> const &)++m_count; static unsigned int live() return m_count; ; We share state between all derived types of same type! c K. Erleben, May 4, 2006 p. 33/36

SFINAE 1 Substitution Failure Is Not An Error, example template<typename T> class IsClass private: typedef char one; // size = 1 byte typedef structchar a[2] two; // size = 2 byte template<typename C> static one test(int C::*); // only classes template<typename C> static two test(...); // anyting else enum yes = sizeof( IsClass<T>::test<T>(0) ); enum no =!yes; ; c K. Erleben, May 4, 2006 p. 34/36

SFINAE 2 Now we can write if( IsClass<my_got_damn_type>::yes ) // do something with class else // do something with non-class Or we might want to write pretty readable code template<typename T> bool is_class(t) if(isclass<t>()::yes) return true; return false; c K. Erleben, May 4, 2006 p. 35/36

SFINAE 3 So now we simply write my_got_damn_type dodah; if( is_class(dodah) )... c K. Erleben, May 4, 2006 p. 36/36