1 / 41

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++, which prompted chuckles from the audience]

zahur
Download Presentation

DEV 321 Understanding and Using Advanced C++ Template Features and Topics on ISO C++

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. DEV 321Understanding and Using Advanced C++ Template Features and Topics on ISO C++ Scott CurrieProgram Manager Visual C++ Microsoft Corporation

  2. 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

  3. 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

  4. 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::TypeList) • Koenig lookup (a.k.a. argument-dependent lookup, ADL) • Summary • Where to find out more • Q & A

  5. 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::TypeList) • Koenig lookup (a.k.a. argument-dependent lookup, ADL) • Summary • Where to find out more • Q & A

  6. 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

  7. 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::TypeList) • Koenig lookup (a.k.a. argument-dependent lookup, ADL) • Summary • Where to find out more • Q & A

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

  9. 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; // a list of intsvector<int> v5( l.begin(), l.end() ); // 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> v6( 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, " " ) );

  10. 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 InputIterator> vector( InputIterator first, InputIterator last /*...*/ ); // ... much more stuff ... };}

  11. 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

  12. 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, p3) • 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

  13. 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::TypeList) • Koenig lookup (a.k.a. argument-dependent lookup, ADL) • Summary • Where to find out more • Q & A

  14. 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 MyType { /* ... */ }; namespace std {template<>// explicit specialization class vector<MyType>// for T == MyType { /* … lots of stuff … */ };} • Note: The above is a complete specialization (we know exactly what all the template arguments are)

  15. Why partial template specialization • But what if your type is itself also a template? template<class T> class MyType { /* ... */ }; 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>// partial specialization class vector<MyType<T> >// for MyType<T> { /* … lots of stuff … */ };}

  16. 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/

  17. 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

  18. 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, NullType> TYPELIST_2(int, double)// Typelist<int, Typelist<double, NullType> > // etc.

  19. Why partial template specialization • Calculate the length of a typelist: template <class TList> struct Length; template <> struct Length<NullType> { 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!)

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

  21. Why partial template specialization • Other operations on typelists: • Search:IndexOf<> • Append:Append<> • Erase:Erase<> • Remove duplicates:NoDuplicates<> • Replace:Replace<> • Partial sort according to an inheritance hierarchy (really!):DerivedToFront<> • 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

  22. Generics + OO = a boatload of power • Something more obviously(?) useful (& with TTPs!): template <class TList, template <class> class Unit>class GenScatterHierarchy; template <class T1, class T2, template<class> class Unit>class GenScatterHierarchy<Typelist<T1, T2>, Unit> : public GenScatterHierarchy<T1, Unit> , public GenScatterHierarchy<T2, Unit> { /*…*/ }; template <class AtomicType, template <class> class Unit>class GenScatterHierarchy : public Unit<AtomicType> { /*…*/ }; template <template <class> class Unit>class GenScatterHierarchy<NullType, Unit> { /*…*/ }; • This lets a class inherit from every type in a flexible list of types.

  23. 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

  24. 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 standard-conforming 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…"

  25. 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!

  26. 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::TypeList) • Koenig lookup (a.k.a. argument-dependent lookup, ADL) • Summary • Where to find out more • Q & A

  27. 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?

  28. 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

  29. 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…)

  30. 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?

  31. 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

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

  33. 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

  34. 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::TypeList) • Koenig lookup (a.k.a. argument-dependent lookup, ADL) • Summary • Where to find out more • Q & A

  35. 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

  36. VC++ and you(r projects) • You now have one of the most standards-conforming 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

  37. 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++ andMore Exceptional C++ (Addison-Wesley, 2000 & 2002) • H. Sutter. Guru of the Week (www.gotw.ca)

  38. Community Resources • MS Community Sites • http://msdn.microsoft.com/visualc • http://gotdotnet.com/team/cplusplus • 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

  39. evaluations

  40. 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::TypeList) • Koenig lookup (a.k.a. argument-dependent lookup, ADL) • Summary • Where to find out more • Q & A

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

More Related