DEV 321 Understanding and Using Advanced C Template

  • Slides: 41
Download presentation
DEV 321 Understanding and Using Advanced C++ Template Features and Topics on ISO C++

DEV 321 Understanding and Using Advanced C++ Template Features and Topics on ISO C++ Scott Currie Program Manager Visual C++ Microsoft Corporation

A word from the field about standards conformance [After saying good things about VC++,

A word from the field about standards conformance [After saying good things about VC++, which prompted chuckles from the audience] "I may complain about Microsoft’s [C++] standards conformance, but it’s a good compiler. If you can get your code through the front end, the back end will generate amazingly efficient executables. " -- Scott Meyers, Boston, March 2002

A word from the field about standards conformance [After saying good things about VC++,

A word from the field about standards conformance [After saying good things about VC++, which prompted chuckles from the audience] "I may complain about Microsoft’s [C++] standards conformance, but it’s a good compiler. If you can get your code through the front end, the back end will generate amazingly efficient executables. " -- Scott Meyers, Boston, March 2002

Agenda Why you should care about conformance A look at particular conformance areas: Member

Agenda Why you should care about conformance A look at particular conformance areas: Member templates (standard "iterator-range" constructors) Partial template specialization (specializing std: : vector; Loki: : Type. List) Koenig lookup (a. k. a. argument-dependent lookup, ADL) Summary Where to find out more Q&A

Agenda Why you should care about conformance A look at particular conformance areas: Member

Agenda Why you should care about conformance A look at particular conformance areas: Member templates (standard "iterator-range" constructors) Partial template specialization (specializing std: : vector; Loki: : Type. List) Koenig lookup (a. k. a. argument-dependent lookup, ADL) Summary Where to find out more Q&A

Why you should care about conformance Library writers Use it daily for PTS and

Why you should care about conformance Library writers Use it daily for PTS and other features The rest of us Can use some techniques directly Library consumption has to work Anyone who uses multiple compilers Easier porting across compilers Lower maintenance and fewer #ifdefs

Agenda Why you should care about conformance A look at particular conformance areas: Member

Agenda Why you should care about conformance A look at particular conformance areas: Member templates (standard "iterator-range" constructors) Partial template specialization (specializing std: : vector; Loki: : Type. List) Koenig lookup (a. k. a. argument-dependent lookup, ADL) Summary Where to find out more Q&A

A look into the standard library The standard library provides some useful containers: std:

A look into the standard library The standard library provides some useful containers: std: : vector<int> v; std: : list<Some. User. Type> l; std: : deque<bool> d; // safer than C-style array // much more flexible, too // pick a data structure… You can construct a container in many ways… vector<int> v 1; vector<int> v 2( 10 ); vector<int> v 3( 10, 42 ); vector<int> v 4( v 1 ); // empty by default // 10 ints with value 0 // 10 ints with value 42 // make a copy of v 1 …but not from another container? list<int> l; vector<int> v 5( l ); // a list of ints // error – but isn’t this a // reasonable thing to do?

Constructing from an iterator range To make this possible, the standard library containers can

Constructing from an iterator range To make this possible, the standard library containers can all be constructed also from an iterator range: list<int> l; vector<int> v 5( l. begin(), l. end() ); // a list of ints // ok – aha! Pointers are iterators too, so construct from an array… int a[] = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 8 }; vector<int> v 6( a, a+14 ); // or, strictly: &a[0], &a[ sizeof(a)/sizeof(int) ] … or even from the console using istream_iterators: vector<string> v( istream_iterator<string>( cin ), (istream_iterator<string>()) ); sort( v. begin(), v. end() ); copy( v. begin(), v. end(), ostream_iterator<string> out( cout, " " ) );

Constructor templates There are infinitely many possible iterator types, so construction from an iterator

Constructor templates There are infinitely many possible iterator types, so construction from an iterator range must be a member template to work with them all: namespace std { template <class T, class Allocator = allocator<T> > class vector { template <class Input. Iterator> vector( Input. Iterator first, Input. Iterator last /*. . . */ ); //. . . much more stuff. . . }; }

VC++ and member templates Of course, there’s more to member template functions than just

VC++ and member templates Of course, there’s more to member template functions than just constructors Templated assignment operators Templated accessor functions Templated conversions etc. Member templates now all work correctly in VC++ 2003 These examples all worked in VC++ 2002 too VC++ 6. 0 could not reliably handle any of this

Limitations of member templates Keep an eye open for a tie-back slide in the

Limitations of member templates Keep an eye open for a tie-back slide in the Partial Template Specialization section A member function template shall not be virtual (14. 5. 2, p 3) Virtual dispatch does not allow compiler to do the right thing statically So, the compiler emits a table of pointers for virtual members of each derived type (VTable) This would cause VTable explosion with a single compiland Impossible with multiple compilands unless a smart linker got involved

Agenda Why you should care about conformance A look at particular conformance areas: Member

Agenda Why you should care about conformance A look at particular conformance areas: Member templates (standard "iterator-range" constructors) Partial template specialization (specializing std: : vector; Loki: : Type. List) Koenig lookup (a. k. a. argument-dependent lookup, ADL) Summary Where to find out more Q&A

A look at std: : vector Here’s that fundamental tool again: namespace std {

A look at std: : vector Here’s that fundamental tool again: namespace std { template <class T, class Allocator = allocator<T> > class vector { /*. . . lots of stuff. . . */ }; } You can specialize vector for your own types: class My. Type { /*. . . */ }; namespace std { template<> // explicit specialization class vector<My. Type> // for T == My. Type { /* … lots of stuff … */ }; } Note: The above is a complete specialization (we know exactly what all the template arguments are)

Why partial template specialization But what if your type is itself also a template?

Why partial template specialization But what if your type is itself also a template? template<class T> class My. Type { /*. . . */ }; namespace std { template<> // explicit specialization? ? ? class vector<? ? ? > // for T == ? ? ? { /* … lots of stuff … */ }; } We couldn’t possibly write out all the complete specializations (even if we wanted to) Instead, we want a “partial” specialization – one that is still parameterized, but for a subset of types: namespace std { template<class T> class vector<My. Type<T> > { /* … lots of stuff … */ }; } // partial specialization // for My. Type<T>

Digression: Boost and Loki Boost Many excellent template libraries that work well with standard

Digression: Boost and Loki Boost Many excellent template libraries that work well with standard library Started by members of C++ Standards Committee Library Working Group Free, open source, peer reviewed http: //www. boost. org/ Loki “A C++ library of designs, containing flexible implementations of common design patterns and idioms” Read Modern C++ Design http: //sourceforge. net/projects/loki-lib/

Digression: auto_ptr Be careful with std: : auto_ptr Do not point auto_ptr at an

Digression: auto_ptr Be careful with std: : auto_ptr Do not point auto_ptr at an array It only deletes. No delete[] Do not put an auto_ptr in a vector Can’t be indexed in a standard way Remember, auto_ptr uses single ownership Use Boost smart pointers instead shared_ptr Performs reference counting Using a shared_ptr to hold the results of every new will nearly eliminate the possibility of memory leaks

A look at Loki: : Typelist Here’s a fundamental tool from Loki, a list

A look at Loki: : Typelist Here’s a fundamental tool from Loki, a list of types: template <class T, class U> struct Typelist { typedef T Head; typedef U Tail; }; Sample usage (simplified by macros ): TYPELIST_1(int) // Typelist<int, Null. Type> TYPELIST_2(int, double) // Typelist<int, Typelist<double, Null. Type> > // etc.

Why partial template specialization Calculate the length of a typelist: template <class TList> struct

Why partial template specialization Calculate the length of a typelist: template <class TList> struct Length; template <> struct Length<Null. Type> { enum { value = 0 }; }; template <class T, class U> // partial specializ. struct Length< Typelist<T, U> > { enum { value = 1 + Length<U>: : value }; }; Sample usage: Length< TYPELIST_3(int, double, bool) >: : value // 3 (Remember, this is all being done at compile time!)

Why partial template specialization Select the Nth type of a typelist: template <class TList,

Why partial template specialization Select the Nth type of a typelist: template <class TList, unsigned index> struct Type. At; template <class Head, class Tail> // partial specializ. struct Type. At<Typelist<Head, Tail>, 0> { typedef Head Result; }; template <class Head, class Tail, unsigned int i> // again struct Type. At<Typelist<Head, Tail>, i> { typedef typename Type. At<Tail, i - 1>: : Result; }; Sample usage: Type. At< TYPELIST_3(int, double, bool), 1>: : Result // double

Why partial template specialization Other operations on typelists: Search: Index. Of<> Append: Append<> Erase:

Why partial template specialization Other operations on typelists: Search: Index. Of<> Append: Append<> Erase: Erase<> Remove duplicates: No. Duplicates<> Replace: Replace<> Partial sort according to an inheritance hierarchy (really!): Derived. To. Front<> Every single one of these requires partial specialization (or "partial workarounds") because they’re defined recursively with a special case (or two) to end the recursion

Generics + OO = a boatload of power Something more obviously(? ) useful (&

Generics + OO = a boatload of power Something more obviously(? ) useful (& with TTPs!): template <class TList, template <class> class Unit> class Gen. Scatter. Hierarchy; template <class T 1, class T 2, template<class> class Unit> class Gen. Scatter. Hierarchy<Typelist<T 1, T 2>, Unit> : public Gen. Scatter. Hierarchy<T 1, Unit> , public Gen. Scatter. Hierarchy<T 2, Unit> { /*…*/ }; template <class Atomic. Type, template <class> class Unit> class Gen. Scatter. Hierarchy : public Unit<Atomic. Type> { /*…*/ }; template <class> class Unit> class Gen. Scatter. Hierarchy<Null. Type, Unit> { /*…*/ }; This lets a class inherit from every type in a flexible list of types.

Member Templates Here is the tie-back Cannot be partially specialized Only explicit specialization How

Member Templates Here is the tie-back Cannot be partially specialized Only explicit specialization How do we achieve similar functionality? Overloading Provides very similar pattern matching Code bloat

A word about compiler-busting Remember, this is all "executed" at compile time! To quote

A word about compiler-busting Remember, this is all "executed" at compile time! To quote Herb Sutter, about Modern C++ Design: "… ‘can compiler XYZ compile Loki? ’ is becoming something of an unofficial benchmark in compiler-writer circles. … Loki is written entirely in normal standardconforming C++ — only more standard and more conforming, it turns out, than some compilers are yet quite ready to digest. Loki … uses templates so widely and heavily that it tears the tar and stresses the stuffing out of some current compilers. In fact, at the time the book was released [2001], no commercially available compiler could compile all of Loki correctly…"

PTS Summary Bread and butter of advanced library writer Provide basis of compile-time programming

PTS Summary Bread and butter of advanced library writer Provide basis of compile-time programming Two types of PTS Template template parameter Specify subset of multiple template parameters Not available for member templates They work in Visual C++. NET 2003 You should use to specialize library types for your own types and templated types Read Modern C++ Design!

Agenda Why you should care about conformance A look at particular conformance areas: Member

Agenda Why you should care about conformance A look at particular conformance areas: Member templates (standard "iterator-range" constructors) Partial template specialization (specializing std: : vector; Loki: : Type. List) Koenig lookup (a. k. a. argument-dependent lookup, ADL) Summary Where to find out more Q&A

A motivating example And now for a word from our standard… namespace NS {

A motivating example And now for a word from our standard… namespace NS { class T { }; void f(T); } NS: : T parm; int main() { f(parm); // no function f() seems to be in } // scope -- is all lost?

A motivating example And now for a word from our standard… namespace NS {

A motivating example And now for a word from our standard… namespace NS { class T { }; void f(T); } NS: : T parm; int main() { f(parm); // OK: calls NS: : f() } The parameter comes from namespace NS, therefore in addition to looking for candidate functions/functors in all the usual places, the compiler is required to also look in NS

How important is it really? Q: Is this purely a notational convenience? What’s so

How important is it really? Q: Is this purely a notational convenience? What’s so hard about writing "NS: : f(parm); " or "using NS: : f; "? #include <iostream> #include <string> // gives std: : operator<<() for strings int main() { std: : string hello = "Hello, world"; std: : operator<<( std: : cout, hello ); // ugh // "std: : cout << hello; " is what we really want } It would be disgraceful if the programmer had to qualify this name, because either the operator couldn’t be used naturally, or the user would have to write "using std: : operator<<; " (tedious) or "using namespace std; " (although I recommend the latter for other reasons…)

Actually, you have it in VC++. NET But VC++ (. NET) 2002 did Koenig

Actually, you have it in VC++. NET But VC++ (. NET) 2002 did Koenig lookup only for operators Happens to be a very common case Happens to speak directly to the foregoing example VC++ 2003 does Koenig lookup for all functions, as required by the standard Useful example of what VC++ 2003 buys you?

Reimplementing std: : swap Basics namespace NS { swap(tuple x, tuple y) {…} tuple<int,

Reimplementing std: : swap Basics namespace NS { swap(tuple x, tuple y) {…} tuple<int, int> x; tuple<int, int> y; … swap(x, y); // OK: calls NS: : swap() } What if swap is out of namespace? namespace NS { swap(tuple x, tuple y) {…} } tuple<int, int> x; tuple<int, int> y; …. swap(x, y); // BAD: calls std: : swap() NS: : swap(x, y); // OK: calls NS: : swap(), but annoying

More std: : swap What if now we want a generic method? namespace NS

More std: : swap What if now we want a generic method? namespace NS { swap(tuple x, tuple y) {…} } tuple<int, int> x; tuple<int, int> y; template <class T> void swap_helper(T source, T target) { …. swap(source, target); // Need Koenig lookup …. } swap_helper <tuple <int, int> > (x, y);

Koenig Summary Argument Dependent Lookup Be aware of operator example Understand what Koenig Lookup

Koenig Summary Argument Dependent Lookup Be aware of operator example Understand what Koenig Lookup is all about Getting around the lack of namespace passing ability to generic code If you use namespaces, be careful about name collisions and the ordering behavior If you use namespaces and generics, you will likely have to depend on this

Agenda Why you should care about conformance A look at particular conformance areas: Member

Agenda Why you should care about conformance A look at particular conformance areas: Member templates (standard "iterator-range" constructors) Partial template specialization (specializing std: : vector; Loki: : Type. List) Koenig lookup (a. k. a. argument-dependent lookup, ADL) Summary Where to find out more Q&A

Best practices (on any good compiler) Know your community and the community libraries: full

Best practices (on any good compiler) Know your community and the community libraries: full STL (see also Effective STL) Standard gets revised, so stay up to date Boost (see www. boost. org) Loki (see www. moderncppdesign. com) etc. Know your power tools: partial specialization (see also Modern C++ Design) Koenig lookup (see also Exceptional C++) member template functions

VC++ and you(r projects) You now have one of the most standardsconforming implementations of

VC++ and you(r projects) You now have one of the most standardsconforming implementations of one of the most powerful and flexible programming languages in the world Use Standard C++ to your best advantage: "Explore, try, perform" Don’t be afraid of making full use of advanced language features Don’t be afraid of exploring and exploiting the full power of community libraries like Boost and Loki and MTL

Further Reading A. Alexandrescu. Modern C++ Design (Addison-Wesley, 2001) The official documentation for the

Further Reading A. Alexandrescu. Modern C++ Design (Addison-Wesley, 2001) The official documentation for the Loki library. See also www. mcppdesign. com and my review of this book at: "Review of Modern C++ Design" (C/C++ Users Journal, 20(4), April 2002), www. gotw. ca/publications/mcd_review. htm N. Josuttis. The C++ Standard Library (Addison-Wesley, 1999) S. Meyers. Effective STL (Addison-Wesley, 2002) H. Sutter. Exceptional C++ and More Exceptional C++ (Addison-Wesley, 2000 & 2002) H. Sutter. Guru of the Week (www. gotw. ca)

Community Resources MS Community Sites http: //msdn. microsoft. com/visualc http: //gotdotnet. com/team/cplus List of

Community Resources MS Community Sites http: //msdn. microsoft. com/visualc http: //gotdotnet. com/team/cplus List of newsgroups http: //msdn. microsoft. com/newsgroups (Visual Tools and Languages -> C/C++) Attend a free chat or webcast http: //microsoft. com/communities/chats/default. mspx http: //microsoft. com/usa/webcasts/default. asp C++ User Groups and Forums http: //www. mvps. org/vcfaq http: //cplus. about. com/cs/visualc http: //www. accu. org http: //www. codeguru. com http: //www. codeproject. com http: //www. devx. com/cplus/Door/7042

evaluations

evaluations

Agenda Why you should care about conformance A look at particular conformance areas: Member

Agenda Why you should care about conformance A look at particular conformance areas: Member templates (standard "iterator-range" constructors) Partial template specialization (specializing std: : vector; Loki: : Type. List) Koenig lookup (a. k. a. argument-dependent lookup, ADL) Summary Where to find out more Q&A

© 2003 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only.

© 2003 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.