logo资料库

Advanced Metaprogramming in Classic C++.pdf

第1页 / 共554页
第2页 / 共554页
第3页 / 共554页
第4页 / 共554页
第5页 / 共554页
第6页 / 共554页
第7页 / 共554页
第8页 / 共554页
资料共554页,剩余部分请下载后查看
Contents at a Glance
Contents
About the Author
About the Technical Reviewer
Acknowledgments
Preface
PART 1: #include
PART 2: #include
PART 3: #include
Index
For your convenience Apress has placed some of the front matter material after the index. Please use the Bookmarks and Contents at a Glance links to access them.
Contents at a Glance About the Author ....................................................................................................xix About the Technical Reviewer ................................................................................xxi Acknowledgments ................................................................................................xxiii Preface ..................................................................................................................xxv ■ #include ................................................................... 1 ■ Chapter 1: Templates ............................................................................................. 3 ■ Chapter 2: Small Object Toolkit ........................................................................... 93 ■ #include ................................................................... 119 ■ Chapter 3: Static Programming ......................................................................... 121 ■ Chapter 4: Overload Resolution ......................................................................... 173 ■ Chapter 5: Interfaces ......................................................................................... 229 ■ Chapter 6: Algorithms ....................................................................................... 275 ■ Chapter 7: Code Generators ............................................................................... 327 ■ Chapter 8: Functors ........................................................................................... 373 ■ Chapter 9: The Opaque Type Principle ............................................................... 415 ■ #include ................................................................. 475 ■ Chapter 10: Refactoring .................................................................................... 477 ■ Chapter 11: Debugging Templates ..................................................................... 501 ■ Chapter 12: C++0x ............................................................................................ 515 vii
■ CONTENTS AT A GLANCE ■ Appendix A: Exercises ....................................................................................... 527 ■ Appendix B: Bibliography .................................................................................. 533 Index ..................................................................................................................... 535 viii
PART 1 #include #include #include
CHAPTER 1 Templates “C++ supports a variety of styles.” Bjarne Stroustrup, A Perspective on ISO C++ Programming is the process of teaching something to a computer by talking to the machine in one of its common languages. The closer to the machine idiom you go, the less natural the words become. Each language carries its own expressive power. For any given concept, there is a language where its description is simpler, more concise, and more detailed. In assembler, we have to give an extremely rich and precise description for any (possibly simple) algorithm, and this makes it very hard to read back. On the other hand, the beauty of C++ is that, while being close enough to the machine language, the language carries enough instruments to enrich itself. C++ allows programmers to express the same concept with different styles and good C++ looks more natural. First you are going to see the connection between the templates and the style, and then you will dig into the details of the C++ template system. Given this C++ fragment: double x = sq(3.14); Can you guess what sq is? It could be a macro: #define sq(x) ((x)*(x)) A function: double sq(double x) { return x*x; } A function template: template inline scalar_t sq(const scalar_t& x) { return x*x; } 3
CHAPTER 1 ■ TEMPLATES A type (an unnamed instance of a class that decays to a double): class sq { double s_; public: sq(double x) : s_(x*x) {} operator double() const { return s_; } }; A global object: class sq_t { public: typedef double value_type; value_type operator()(double x) const { return x*x; } }; const sq_t sq = sq_t(); Regardless of how sq(3.14) is implemented, most humans can guess what sq(3.14) does just looking at it. However, visual equivalence does not imply interchangeableness. If sq is a class, for example, passing a square to a function template will trigger an unexpected argument deduction: template void f(T x); f(cos(3.14)); // instantiates f f(sq(3.14)); // instantiates f. counterintuitive? Furthermore, you would expect every possible numeric type to be squared as efficiently as possible, but different implementations may perform differently in different situations: std::vector v; std::transform(v.begin(), v.end(), v.begin(), sq); If you need to transform a sequence, most compilers will get a performance boost from the last implementation of sq (and an error if sq is a macro). 4
CHAPTER 1 ■ TEMPLATES The purpose of TMP is to write code that is: •฀ •฀ •฀ Visually clear to human users so that nobody needs to look underneath. Efficient in most/all situations from the point of view of the compiler. 1 Self-adapting to the rest of the program. Self-adapting means “portable” (independent of any particular compiler) and “not imposing constraints”. An implementation of sq that requires its argument to derive from some abstract base class would not qualify as self-adapting. The true power of C++ templates is style. Compare the following equivalent lines: double x1 = (-b + sqrt(b*b-4*a*c))/(2*a); double x2 = (-b + sqrt(sq(b)-4*a*c))/(2*a); All template argument computations and deductions are performed at compile time, so they impose no runtime overhead. If the function sq is properly written, line 2 is at least as efficient as line 1 and easier to read at the same time. Using sq is elegant: •฀ •฀ •฀ It makes code readable or self-evident It carries no speed penalty It leaves the program open to future optimizations In fact, after the concept of squaring has been isolated from plain multiplication, you can easily plug in specializations: template inline scalar_t sq(const scalar_t& x) { return x*x; } template <> inline double sq(const double& x) { // here, use any special algorithm you have! } 1Loosely฀speaking,฀that’s฀the฀reason฀for฀the฀“meta”฀prefix฀in฀“metaprogramming”. 5
分享到:
收藏