PROGRAMMING TECHNIQUES Based on “Modern C++ Design” BY ALEXANDRESCU BOGDAN PENKOVSKY 2010.

Slides:



Advertisements
Similar presentations
Object Oriented Programming
Advertisements

The C ++ Language BY Shery khan. The C++ Language Bjarne Stroupstrup, the language’s creator C++ was designed to provide Simula’s facilities for program.
Object Orientation Chapter SixteenModern Programming Languages, 2nd ed.1 Spring 2012.
Object Orientation Chapter SixteenModern Programming Languages, 2nd ed.1.
Exceptions, Templates, And The Standard Template Library (STL) Chapter 16.
Copyright © 2012 Pearson Education, Inc. Chapter 16: Exceptions, Templates, and the Standard Template Library (STL)
C++ How to Program, 7/e © by Pearson Education, Inc. All Rights Reserved.
Chapter 10.
Chapter 16 Templates. Copyright © 2006 Pearson Addison-Wesley. All rights reserved Learning Objectives  Function Templates  Syntax, defining 
C++ Training Datascope Lawrence D’Antonio Lecture 1 Quiz 1.
 2006 Pearson Education, Inc. All rights reserved. Templates (again)CS-2303, C-Term Templates (again) CS-2303 System Programming Concepts (Slides.
Templates. Objectives At the conclusion of this lesson, students should be able to Explain how function templates are used Correctly create a function.
Templates. Example… A useful routine to have is void swap(int &a, int &b){ int tmp = a; a = b; b = tmp; }
Classes. Class expanded concept of a data structure: instead of holding only data, it can hold both data and functions. An object is an instantiation.
1 Procedural Concept The main program coordinates calls to procedures and hands over appropriate data as parameters.
C++ Functions. 2 Agenda What is a function? What is a function? Types of C++ functions: Types of C++ functions: Standard functions Standard functions.
Computer Science and Software Engineering University of Wisconsin - Platteville 7. Inheritance and Polymorphism Yan Shi CS/SE 2630 Lecture Notes.
CSE 332: C++ templates and generic programming I Motivation for Generic Programming in C++ We’ve looked at procedural programming –Reuse of code by packaging.
Intro to Generic Programming Templates and Vectors.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 19 Clicker Questions November 3, 2009.
CSE 332: C++ templates This Week C++ Templates –Another form of polymorphism (interface based) –Let you plug different types into reusable code Assigned.
Inheritance. Recall the plant that we defined earlier… class Plant { public: Plant( double theHeight ) : hasLeaves( true ), height (theHeight) { } Plant(
© The McGraw-Hill Companies, 2006 Chapter 4 Implementing methods.
Polymorphism Lecture-10. Print A Cheque A Report A Photograph PrintCheque() PrintReport() PrintPhoto() Printing.
Department of Computer Science and Engineering, HKUST 1 HKUST Summer Programming Course 2008 Templates ~ their instantiation and specialization.
CMSC 202 Generics. Nov Generalized Code One goal of OOP is to provide the ability to write reusable, generalized code. Polymorphic code using.
CSE 332: C++ Type Programming: Associated Types, Typedefs and Traits A General Look at Type Programming in C++ Associated types (the idea) –Let you associate.
CHAPTER 3 Function Overloading. 2 Introduction The polymorphism refers to ‘one name having many forms’ ‘different behaviour of an instance depending upon.
Computer Science and Software Engineering University of Wisconsin - Platteville 2. Pointer Yan Shi CS/SE2630 Lecture Notes.
CNS  Executive Overview  Template Parameters  Function Template Issues 2 CNS Templates.
Programming Languages by Ravi Sethi Chapter 6: Groupings of Data and Operations.
GPCE'04, Vancouver 1 Towards a General Template Introspection Library in C++ István Zólyomi, Zoltán Porkoláb Department of Programming Languages and Compilers.
CSE 425: Data Types I Data and Data Types Data may be more abstract than their representation –E.g., integer (unbounded) vs. 64-bit int (bounded) A language.
CS212: Object Oriented Analysis and Design Lecture 9: Function Overloading in C++
More About Objects and Methods Chapter 5. Outline Programming with Methods Static Methods and Static Variables Designing Methods Overloading Constructors.
Programming in Java CSCI-2220 Object Oriented Programming.
C# Classes and Inheritance CNS 3260 C#.NET Software Development.
Nirmalya Roy School of Electrical Engineering and Computer Science Washington State University Cpt S 122 – Data Structures Templates.
CPSC 252 The Big Three Page 1 The “Big Three” Every class that has data members pointing to dynamically allocated memory must implement these three methods:
Input Validation 10/09/13. Input Validation with if Statements You, the C++ programmer, doing Quality Assurance (by hand!) C++ for Everyone by Cay Horstmann.
Effective C++, 2nd Ed. By Scott Myers. Constructors, Destructors, and Assignment Operators 11.Define a copy constructor and an assignment operator for.
©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
Introduction to Object-Oriented Programming Lesson 2.
Fall 2015CISC/CMPE320 - Prof. McLeod1 CISC/CMPE320 Assignment 4 is due Nov. 20 (next Friday). After today you should know everything you need for assignment.
Interfaces and Inner Classes
1 Becoming More Effective with C++ … Day Two Stanley B. Lippman
Quick Review of OOP Constructs Classes:  Data types for structured data and behavior  fields and methods Objects:  Variables whose data type is a class.
Classes - Part II (revisited) n Constant objects and member functions n Definition Form of Member Functions n friend functions and friend classes n Constructors.
Recap Introduction to Inheritance Inheritance in C++ IS-A Relationship Polymorphism in Inheritance Classes in Inheritance Visibility Rules Constructor.
Array and Pointers An Introduction Unit Unit Introduction This unit covers the usage of pointers and arrays in C++
Chapter 16 Templates Copyright © 2008 Pearson Addison-Wesley. All rights reserved.
CSE 332: C++ templates and generic programming II Review: Concepts and Models Templates impose requirements on type parameters –Types that are plugged.
Copyright 2006 Pearson Addison-Wesley, 2008, 2012 Joey Paquet 1 Concordia University Department of Computer Science and Software Engineering SOEN6441 –
CS 342: C++ Overloading Copyright © 2004 Dept. of Computer Science and Engineering, Washington University Overview of C++ Overloading Overloading occurs.
 Virtual Function Concepts: Abstract Classes & Pure Virtual Functions, Virtual Base classes, Friend functions, Static Functions, Assignment & copy initialization,
CSE 332: C++ Overloading Overview of C++ Overloading Overloading occurs when the same operator or function name is used with different signatures Both.
Value Types. 2 Objectives Discuss concept of value types –efficiency –memory management –value semantics –boxing –unboxing –simple types Introduce struct.
Motivation for Generic Programming in C++
C++ Lesson 1.
Programming with ANSI C ++
7. Inheritance and Polymorphism
Type Traits By Reggie Meisler.
Introduction to Computer Science / Procedural – 67130
Java Primer 1: Types, Classes and Operators
Review: Two Programming Paradigms
Student Book An Introduction
The dirty secrets of objects
Programming with ANSI C ++
Java Programming Language
Presentation transcript:

PROGRAMMING TECHNIQUES Based on “Modern C++ Design” BY ALEXANDRESCU BOGDAN PENKOVSKY 2010

PROGRAMMING TECHNIQUES WHAT’S ALL THIS STAFF ABOUT?

PROGRAMMING TECHNIQUES WHAT’S ALL THIS STAFF ABOUT? Through all the “Modern C++ design” some essential techniques are stretched. Bold knowledge of them will help to understand main ideas and… create powerful idioms. So, we’re going to review and discuss main PROGRAMMING TECHNIQUES

PROGRAMMING TECHNIQUES TECHNIQUES Compile-Time Assertions Partial Template Specialization Local Classes Mapping Integral Constants to Types Type-to-Type Mapping

PROGRAMMING TECHNIQUES TECHNIQUES Type Selection Detecting Convertibility and Inheritance at Compile Time A Wrapper Around type_info NullType and EmptyType Type Traits

PROGRAMMING TECHNIQUES The need for better static checking (and more customizable error messages) template To safe_reinterpret_cast(From from) { assert (sizeof(From) <= sizeof(To)); return reinterpret_cast(from); } int i=…; char*p=safe_reinterpret_cast (i);

PROGRAMMING TECHNIQUES Safe_reinterpret_cast function Problem: Runtime detecting. Detecting on compilation would be better. Reason: Porting the application to a new compiler might leave the bug dormant until it crashes the program in front of your customer.

PROGRAMMING TECHNIQUES Compile time assertion #define STATIC_CHECK(expr) { char unnamed[( expr)? :1 : 0]; } template To safe_reinterpret_cast(From from) { STATIC_CHECK(sizeof(From) <= sizeof(To)); return reinterpret_cast (from); } void* somePointer=…; char c=safe_reinterpret_cast (somePointer);

PROGRAMMING TECHNIQUES Static_check Non zero-length array approach Problem: Not terribly informative: "Cannot create array of size zero" does not suggest "Type char is too narrow to hold a pointer."

PROGRAMMING TECHNIQUES What we can improve? A better solution is to rely on a template with an informative name; the compiler will mention the name of that template in the error message

PROGRAMMING TECHNIQUES Template CompileTimeChecker template struct CompileTimeChecker; { CompileTimeChecker(…); }; template<> struct CompileTimeChecker {}; #define STATIC_CHECK(expr, msg) \ {\ class ERROR_##msg {}; \ (void)sizeof(CompileTimeChecker ((ERROR_##msg())));\ }

PROGRAMMING TECHNIQUES Let’s test Assume that sizeof(char) < sizeof(void*) (not guaranteed) template To safe_reinterpret_cast(From from) { STATIC_CHECK(sizeof(From) <= sizeof(To), Destination_Type_Too_Narrow); return reinterpret_cast (from); }... void* somePointer =...; char c = safe_reinterpret_cast (somePointer);

PROGRAMMING TECHNIQUES After macro preprocessing template To safe_reinterpret_cast(From from) {  { class ERROR_Destination_Type_Too_Narrow {}; (void)sizeof( CompileTimeChecker ( ERROR_Destination_Type_Too_Narrow ()));  } return reinterpret_cast (from); }

PROGRAMMING TECHNIQUES Template CompileTimeChecker Now here is a trick! The CompileTimeChecker specialization has a constructor that accepts anything. This means that if the expression checked evaluates to true, the resulting program is valid. If the comparison between sizes evaluates to false we can see a message: "Error: Cannot convert ERROR_Destination_Type_Too_Narrow to CompileTimeChecker."

PROGRAMMING TECHNIQUES NOT BAD? LET’S MOVE FORWARD!

PROGRAMMING TECHNIQUES ONLY ABOUT 50 SLIDES LEFT!

PROGRAMMING TECHNIQUES Partial Template Specialization template class Widget {.. Generic implementation... }; And explicit specialization: template <> class Widget {... Specialized implementation... };

PROGRAMMING TECHNIQUES Partial Template Specialization It allows to specialize a class template for subsets of that template's possible instantiations set. Typically, in a partial specialization of a class template, it is specified only some of the template arguments and the other ones are left generic.

PROGRAMMING TECHNIQUES Capabilities When you instantiate a template, the compiler does a pattern matching of existing partial and total specializations to find the best candidate This gives an enormous flexibility.

PROGRAMMING TECHNIQUES Partial Template Flexibility template class Widget, MyController> {... further specialized implementation... };

PROGRAMMING TECHNIQUES Limitations Although you can totally specialize member functions of a class template, you cannot partially specialize member functions. You cannot partially specialize namespace-level (nonmember) template functions. The only closest is overloading. So you have fine-grained specialization abilities only for the function parameters That is because “bad” compiler writers make their lives easier.

PROGRAMMING TECHNIQUES Partial Function Templates template T Fun(U obj); // primary template template void Fun (U obj); // illegal partial // specialization template T Fun (Window obj); //legal (overloading)

PROGRAMMING TECHNIQUES LOCAL CLASSES void Fun() { class Local {... methods... };... code used by local class... }

PROGRAMMING TECHNIQUES Limitations There’s no way to define static member variables No way to access nonstatic local variables Any idiom that uses a local class can be implemented using a template class outside the function

PROGRAMMING TECHNIQUES Advantages Local classes defined inside template functions can use the template parameters of the enclosing function Unique feature: local classes are final. Without them, you'd have to add an unnamed namespace in a separate translation unit.

PROGRAMMING TECHNIQUES LOCAL CLASSES INSIDE TEMPLATE FUNCTIONS (idiom) class Interface { public: virtual void Fun() =0; … };

PROGRAMMING TECHNIQUES INSIDE TEMPLATE FUNCTIONS template Interface* MakeAdapter(const T& obj, const P& arg) { class Local : public Interface { public: Local(const T& obj, const P& arg): obj_(obj), arg_(arg) {} virtual void Fun() { obj_.Call(arg_); } private: T obj_; P arg_; }; return new Local(obj, arg); }

PROGRAMMING TECHNIQUES Mapping Integral Constants to Types template struct lnt2Type { enum { value = v }; };

PROGRAMMING TECHNIQUES Mapping Integral Constants to Types Int2Type generates a distinct type for each distinct constant integral value passed. Can be used whenever there’s need to "typify" an integral constant quickly Achieves dispatching on a constant integral value.

PROGRAMMING TECHNIQUES Int2Type Typical use: You need to call one of several different functions, depending on a compile-time constant. You need to do this dispatch at compile time. Differently from else-if statement, Int2Type doesn’t require compilation of both code branches. I.E.:

PROGRAMMING TECHNIQUES NiftyContainer template class NiftyContainer { void DoSomething() { T* pSomeObj =...; if (isPolymorphic) { T* pNewObj = pSomeObj->clone();... polymorphic algorithm … } else { T* pNewObj = new T(*pSomeObj);... nonpolymorphic algorithm... } };

PROGRAMMING TECHNIQUES NiftyContainer The problem is that the compiler won't let you get away with this code. The compiler diligently tries to compile both branches, even if the optimizer will later eliminate the dead code. How to avoid: you can use Int2Type with simple overloading

PROGRAMMING TECHNIQUES NiftyContainer template class NiftyContainer { private: void DoSomething(T* pObj, Int2Type ) { T* pNewObj = pObj->Clone();... polymorphic algorithm... } …

PROGRAMMING TECHNIQUES NiftyContainer … void DoSomething(T* pObj, lnt2Type ) { T* pNewObj = new T(*pObj);... nonpolymorphic algorithm... } public: void DoSomething(T* pObj) { DoSomething(pObj, lnt2Type ()) ; } };

PROGRAMMING TECHNIQUES Type-to-Type Mapping Consider: template T* Create(const U& arg, T /* dummy */ ) { return new T(arg); } Now say there is Objects of type Widget that must take two arguments upon construction

PROGRAMMING TECHNIQUES Obvious solution template Widget* Create (const U& arg) { return new Widget(arg, -1); }

PROGRAMMING TECHNIQUES Obvious solution template Widget* Create (const U& arg) { return new Widget(arg, -1); } FAILS TO COMPILE!

PROGRAMMING TECHNIQUES Type-to-Type Mapping //Overloading only template T* Create(const U& arg, T /* dummy */) { return new T(arg); } template Widget* Create(const U& arg, Widget /* dummy */) { return new Widget(arg, -1); }

PROGRAMMING TECHNIQUES Type-to-Type Mapping Such a solution would incur the overhead of constructing an arbitrarily complex object that remains unused. We need a light vehicle for transporting the type information about T to Create. So let’s look forward:

PROGRAMMING TECHNIQUES Type-to-Type Mapping template struct Type2Type { typedef T OriginalType; }; Type2Type is devoid of any value, but distinct types lead to distinct Type2Type instantiations, which is what we need.

PROGRAMMING TECHNIQUES Create based on overloading & Type2Type template //better implementation T* Create(const U& arg, Type2Type ) { return new T(arg); } template Widget* Create(const U& arg, Type2Type ) { return new Widget(arg, -1); } String* pStr = Create("Hello", Type2Type ()); Widget* pW = Create(100, Type2Type ());

PROGRAMMING TECHNIQUES Type Selection Sometimes generic code needs to select one type or another, depending on a Boolean constant. template struct NiftyContainervalueTraits { typedef T* ValueType; };

PROGRAMMING TECHNIQUES Type Selection template struct NiftyContainervalueTraits { typedef T* ValueType; }; template class NiftyContainer { typedef NiftyContainerValueTraits Traits; typedef typename Traits::ValueType ValueType; };

PROGRAMMING TECHNIQUES Type Selection This way of doing things is unnecessarily clumsy. It doesn't scale: for each type selection, you must define a new traits class template. The library class template Select provided by Loki makes type selection available right on the spot. Its definition uses partial template specialization.

PROGRAMMING TECHNIQUES Template Select template struct Select { typedef T Result; }; Template struct Select { typedef U Result; };

PROGRAMMING TECHNIQUES Template Select How it works: If flag evaluates to true, the compiler uses the first (generic) definition, therefore Result evaluates to T. If flag is false, then the specialization enters into action and Result evaluates to U.

PROGRAMMING TECHNIQUES Moving on…

PROGRAMMING TECHNIQUES Detecting Convertibility and Inheritance at Compile Time Given two arbitrary types T and U that you know nothing about, how can you detect whether or not U inherits from T? How can you detect whether an arbitrary type T supports automatic conversion to an arbitrary type U?

PROGRAMMING TECHNIQUES Detecting Convertibility and Inheritance at Compile Time Solution relies on sizeof: it could be applied to any expression, no matter how complex, getting its size without actually evaluating that expression at runtime

PROGRAMMING TECHNIQUES Detecting Convertibility and Inheritance at Compile Time template class Conversion { typedef char Small; class Big { char dummy[2]; }; static Small Test(U); static Big Test(...); ….

PROGRAMMING TECHNIQUES Detecting Convertibility and Inheritance at Compile Time static T MakeT(); public: enum { exists = sizeof(Test(MakeT())) == sizeof(Small) }; };

PROGRAMMING TECHNIQUES Detecting Convertibility and Inheritance at Compile Time int main() { using namespace std; cout « Conversion ::exists « ' ' « Convesrion >::exists « ' '; }

PROGRAMMING TECHNIQUES Conversion We can implement one more constant inside Conversion: sameType, which is true if T and U represent the same type: template class Conversion {... as above... enum { sameType = false }; };

PROGRAMMING TECHNIQUES Conversion We implement sameType through a partial specialization of Conversion template class Conversion { public: enum { exists = 1, sameType = 1 }; };

PROGRAMMING TECHNIQUES SuperSubClass Macro //With the help of Conversion, it is now very //easy to determine inheritance #define SUPERSUBCLASS(T, U) \ (Conversion ::exists\ && \ !Conversion ::sameType);

PROGRAMMING TECHNIQUES SuperSubClass Macro SUPERSUBCLASS(T, U) evaluates to true if U inherits from T publicly, or if T and U are actually the same type. SUPERSUBCLASS does its job by evaluating the convertibility from a const U* to a const T*.

PROGRAMMING TECHNIQUES In the next slides: A wrapper around type_info NullType and EmptyType – the helpful helpers ;) …and finally: TypeTraits

PROGRAMMING TECHNIQUES Standard type_info class std::type_info gives the ability to investigate object types at runtime Hard to exploit: Disables the copy constructor and assignment operator, which makes storing type_info objects impossible. Does not guarantee that each invocation returns a reference to the same type_info object.

PROGRAMMING TECHNIQUES Loki wrapper class solution class TypeInfo { public: TypeInfo(); TypeInfo(const std::type_info&); TypeInfo(const TypeInfo&); TypeInfo& operator==(const TypeInfo&); bool before(const TypeInfo&) const; const char* name() const; private: const std::type_info* pInfo_; }

PROGRAMMING TECHNIQUES Loki wrapper class solution // Comparison operators bool operator==(const TypeInfo&, const TypeInfo&); bool operator!=(const TypeInfo&, const TypeInfo&); bool operator<(const TypeInfo&, const TypeInfo&); bool operator<=(const TypeInfo&, const TypeInfo&); bool operator>(const TypeInfo&, const TypeInfo&); bool operator>=(const TypeInfo&, const TypeInfo&);

PROGRAMMING TECHNIQUES Loki wrapper class solution // Now you can directly compare objects of type TypeInfo and std::type_info void Fun(Base* pObj) { TypeInfo info = typeid(Derived);... if (typeid(*pObj) == info) {... pBase actually points to a Derived object... }... }

PROGRAMMING TECHNIQUES Important features The ability to copy and compare TypeInfo objects is important in many situations. The cloning factory in and one double- dispatch engine provided in future seminars put TypeInfo to good use.

PROGRAMMING TECHNIQUES NullType & EmptyType helper Classes class NullType {}; Used for cases in which a type must be there syntactically but doesn't have a semantic sense. struct EmptyType {}; EmptyType is a legal type to inherit from, and you can pass around values of type EmptyType Will be used later in TypeLists

PROGRAMMING TECHNIQUES Type Traits Traits are a generic programming technique that allows compile-time decisions to be made based on types, much as you would make runtime decisions based on values “Extra level of indirection" that solves many software engineering problems Type-related decisions outside the immediate context in which they are made.

PROGRAMMING TECHNIQUES Copying application template OutIt Copy(Init first, Init last, OutIt result) { for (; first != last; ++first, ++result) *result = *first; }

PROGRAMMING TECHNIQUES Implementing Pointer Traits //T is not a pointer, and a pointee type doesn't apply. template class TypeTraits { private: template struct PointerTraits { enum(result = false }; typedef NullType PointeeType; }; …

PROGRAMMING TECHNIQUES Implementing Pointer Traits //A better match than the generic template for any pointer type. template struct PointerTraits { enum { result = true }; typedef U PointeeType; }; public: enum { isPointer = PointerTraits ::result }; typedef PointerTraits ::PointeeType PointeeType; };

PROGRAMMING TECHNIQUES Summary