C++模板元编程(英文版)

C++模板元编程(英文版)

C++模板元编程,来源与Boost的MPL库的经验总结,对C++模板元编程进行了深入细致的讲解。已经证明C++模板是图灵完备的。强烈建议学习C++的朋友看一下。

基本信息
  C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond
By David Abrahams, Aleksey Gurtovoy
 
  Publisher : Addison Wesley Professional
  Pub Date : December 10, 2004
  ISBN : 0-321-22725-5
  Pages : 400

词汇解释
  元编程(Metaprogramming): 编程序的程序.
  C++模板元编程(Templete Metaprogramming): 使用C++模板技术来实现编译期类型选择/数值计算等,从而提高代码的灵活性和提高数学运算的性能。C++模板元编程技术已经被应用于多个高性能数学运算库的实现,并取得了显著效果。准C++库Boost提供了体系完整的MPL(Meta Program Lib. )库,并大量使用了这种技巧是底层库的实现更灵活高效。

简介
  "If you're like me, you're excited by what people do with template metaprogramming (TMP) but are frustrated at the lack of clear guidance and powerful tools. Well, this is the book we've been waiting for. With help from the excellent Boost Metaprogramming Library, David and Aleksey take TMP from the laboratory to the workplace with readable prose and practical examples, showing that "compile-time STL" is as able as its runtime counterpart. Serving as a tutorial as well as a handbook for experts, this is the book on C++ template metaprogramming."Chuck Allison, Editor, The C++ Source

C++ Template Metaprogramming sheds light on the most powerful idioms of today's C++, at long last delivering practical metaprogramming tools and techniques into the hands of the everyday programmer.

A metaprogram is a program that generates or manipulates program code. Ever since generic programming was introduced to C++, programmers have discovered myriad "template tricks" for manipulating programs as they are compiled, effectively eliminating the barrier between program and metaprogram. While excitement among C++ experts about these capabilities has reached the community at large, their practical application remains out of reach for most programmers. This book explains what metaprogramming is and how it is best used. It provides the foundation you'll need to use the template metaprogramming effectively in your own work.

This book is aimed at any programmer who is comfortable with idioms of the Standard Template Library (STL). C++ power-users will gain a new insight into their existing work and a new fluency in the domain of metaprogramming. Intermediate-level programmers who have learned a few advanced template techniques will see where these tricks fit in the big picture and will gain the conceptual foundation to use them with discipline. Programmers who have caught the scent of metaprogramming, but for whom it is still mysterious, will finally gain a clear understanding of how, when, and why it works. All readers will leave with a new tool of unprecedented power at their disposalthe Boost Metaprogramming Library.

前言
  In 1998 Dave had the privilege of attending a workshop in Generic Programming at Dagstuhl Castle in Germany. Near the end of the workshop, a very enthusiastic Kristof Czarnecki and Ullrich Eisenecker (of Generative Programming fame) passed out a few pages of C++ source code that they billed as a complete Lisp implementation built out of C++ templates. At the time it appeared to Dave to be nothing more than a curiosity, a charming but impractical hijacking of the template system to prove that you can write programs that execute at compile time. He never suspected that one day he would see a role for metaprogramming in most of his day-to-day programming jobs. In many ways, that collection of templates was the precursor to the Boost Metaprogramming Library (MPL): It may have been the first library designed to turn compile-time C++ from an ad hoc collection of "template tricks" into an example of disciplined and readable software engineering. With the availability of tools to write and understand metaprograms at a high level, we've since found that using these techniques is not only practical, but easy, fun, and often astoundingly powerful.

Despite the existence of numerous real systems built with template metaprogramming and the MPL, many people still consider metaprogramming to be other-worldly magic, and often as something to be avoided in day-to-day production code. If you've never done any metaprogramming, it may not even have an obvious relationship to the work you do. With this book, we hope to lift the veil of mystery, so that you get an understanding not only of how metaprogramming is done, but also why and when. The best part is that while much of the mystery will have dissolved, we think you'll still find enough magic left in the subject to stay as inspired about it as we are.

Dave and Aleksey


摘录
  1.2. So What's a Metaprogram? (什么是元编程)
  If you dissect the word metaprogram literally, it means "a program about a program."[1] A little less poetically, a metaprogram is a program that manipulates code. It may be an odd-sounding concept, but you're probably already familiar with several such beasts. Your C++ compiler is one example: it manipulates your C++ code to produce assembly language or machine code.

(1) In philosophy and, as it happens, programming, the prefix "meta" is used to mean "about" or "one level of description higher," as derived from the original Greek meaning "beyond" or "behind."

Parser generators such as YACC [Joh79] are another kind of program-manipulating program. The input to YACC is a high-level parser description written in terms of grammar rules and attached actions brace-enclosed. For instance, to parse and evaluate arithmetic expressions with the usual precedence rules, we might feed YACC the following grammar description:

  expression : term
        | expression '+' term { $$ = $1 + $3; }
        | expression '-' term { $$ = $1 - $3; }
        ;
  term : factor
    | term '*' factor { $$ = $1 * $3; }
    | term '/' factor { $$ = $1 / $3; }
    ;

  factor : INTEGER
      | group
      ;

  group : '(' expression ')'
      ;



In response, YACC would generate a C/C++ source file containing (among other things), a yyparse function that we can call to parse text against the grammar and execute the appropriate actions:[2]

(2) This is provided that we also implemented an appropriate yylex function to tokenize the text. See Chapter 10 for a complete example or, better yet, pick up a YACC manual.

  int main()
  {
  extern int yyparse();
  return yyparse();
  }



The user of YACC is operating mostly in the domain of parser design, so we'll call YACC's input language the domain language of this system. Because the rest of the user's program typically requires a general-purpose programming system and must interact with the generated parser, YACC translates the domain language into the host language, C, which the user then compiles and links together with her other code. The domain language thus undergoes two translation steps, and the user is always very conscious of the boundary between it and the rest of her program.

1.4. Metaprogramming in C++ (C++模板元编程)
In C++, it was discovered almost by accident [Unruh94], [Veld95b] that the template mechanism provides a rich facility for native language metaprogramming. In this section we'll explore the basic mechanisms and some common idioms used for metaprogramming in C++.

1.4.1. Numeric Computations
The earliest C++ metaprograms performed integer computations at compile time. One of the very first metaprograms was shown at a C++ committee meeting by Erwin Unruh; it was actually an illegal code fragment whose error messages contained a sequence of computed prime numbers!

Since illegal code is hard to use effectively in a larger system, let's examine a slightly more practical application. The following metaprogram (which lies at the heart of our little compiler test above) transliterates unsigned decimal numerals into their binary equivalents, allowing us to express binary constants in a recognizable form.

  template <unsigned long N>
  struct binary
  {
    static unsigned const value
      = binary<N/10>::value << 1   // prepend higher bits
        | N%10;             // to lowest bit
  };

  template <>                   // specialization
  struct binary<0>               // terminates recursion
  {
    static unsigned const value = 0;
  };

  unsigned const one   =   binary<1>::value;
  unsigned const three =   binary<11>::value;
  unsigned const five = binary<101>::value;
  unsigned const seven = binary<111>::value;
  unsigned const nine = binary<1001>::value;



If you're wondering "Where's the program?" we ask you to consider what happens when we access the nested ::value member of binary<N>. The binary template is instantiated again with a smaller N, until N reaches zero and the specialization is used as a termination condition. That process should have the familiar flavor of a recursive function calland what is a program, after all, but a function? Essentially, the compiler is being used to interpret our little metaprogram.

Error Checking
There's nothing to prevent a user from passing binary a number such as 678, whose decimal representation is not also valid binary. The result would make a strange sort of sense (it would be 6x22 + 7x21 + 8x20), but nonetheless an input like 678 probably indicates a bug in the user's logic. In Chapter 3 we'll show you how to ensure that binary<N>::value only compiles when N's decimal representation is composed solely of 0s and 1s.

Because the C++ language imposes a distinction between the expression of compile-time and runtime computation, metaprograms look different from their runtime counterparts. As in Scheme, the C++ metaprogrammer writes her code in the same language as the ordinary program, but in C++ only the compile-time subset of the full language is available to her. Compare the previous example with this straightforward runtime version of binary:

  unsigned binary(unsigned long N)
  {
    return N == 0 ? 0 : N%10 + 2 * binary(N/10);
  }



A key difference between the runtime and compile time versions is the way termination conditions are handled: our meta-binary uses template specialization to describe what happens when N is zero. Terminating specializations are a common characteristic of nearly all C++ metaprograms, though in some cases they will be hidden behind the interface of a metaprogramming library.

Another important difference between runtime and compile time C++ is highlighted by this version of binary, which uses a for loop in lieu of recursion.

  unsigned binary(unsigned long N)
  {
    unsigned result = 0;
    for (unsigned bit = 0x1; N; N /= 10, bit <<= 1)
    {
      if (N%10)
          result += bit;
    }
    return result;
  }



Though more verbose than the recursive version, many C++ programmers will be more comfortable with this one, not least because at runtime iteration is sometimes more efficient than recursion.

The compile-time part of C++ is often referred to as a "pure functional language" because of a property it shares with languages such as Haskell: (meta)data is immutable and (meta)functions can have no side effects. As a result, compile-time C++ has nothing corresponding to the non-const variables used in runtime C++. Since you can't write a (non-infinite) loop without examining some mutable state in its termination condition, iteration is simply beyond reach at compile time. Therefore, recursion is idiomatic for C++ metaprograms.

1.4.2. Type Computations
Much more important than its ability to do compile time numeric computations is C++'s ability to compute with types. As a matter of fact, type computation will dominate the rest of this book, and we'll cover examples of it in the very first section of the next chapter. By the time we're through, you'll probably think of template metaprogramming as "computing with types."

Although you may have to read Chapter 2 to understand the specifics of type computation, we'd like to give you a sense of its power. Remember our YACC expression evaluator? It turns out we don't need to use a translator to get that kind of power and convenience. With appropriate surrounding code from the Boost Spirit library, the following legal C++ code has equivalent functionality.

  expr =
      ( term[expr.val = _1] >> '+' >> expr[expr.val += _1] )
    | ( term[expr.val = _1] >> '-' >> expr[expr.val -= _1] )
    | term[expr.val = _1]
    ;

  term =
      ( factor[term.val = _1] >> '*' >> term[term.val *= _1] )
    | ( factor[term.val = _1] >> '/' >> term[term.val /= _1] )
    | factor[term.val = _1]
    ;

  factor =
      integer[factor.val = _1]
    | ( '(' >> expr[factor.val = _1] >> ')' )
    ;



Each assignment stores a function object that parses and evaluates the bit of grammar on its right hand side. The behavior of each stored function object, when invoked, is determined entirely by the type of the expression used to construct it, and the type of each expression is computed by a metaprogram associated with the various operators used.

Just like YACC, the Spirit library is a metaprogram that generates parsers from grammar specifications. Unlike YACC, Spirit defines its domain language as a subset of C++ itself. If you don't see how that's possible at this point, don't worry. By the time you finish this book, you will.

下载
Addison.Wesley.C.Plus.Plus.Template.Metaprogramming.Dec.2004.chm
 

内容简介 本书是关于C++模板编程的著作。本书主要介绍Traits和类型操纵、深入探索函数、整型外覆器和操作、序列与迭代器、算法、视图与迭代器适配器、诊断、跨越编译期和运行期边界、领域特定的嵌入式语言、DSEL设计演练,另外附录部分还介绍了预处理编程概述、typename和template关键字。本书通过理论联系实践,深入讲解了C++高级编程技术。. 本书适合中、高阶C++程序员等参考。.. 本书清晰地揭示了现代C++最具威力的使用手法,将实际的工具和技术交付普通程序员的手中。 编程是产生或操纵程序码的程序。自从泛型编程被引入C++中以来,程序员们已经发现用于当程序被编译时对其进行操纵的无数“tricks template”,这些tricks有效地消除了横亘在程序和编程之间的藩篱。尽管C++专家们对这种能力的兴奋已经波及整个C++社区,然而它们的实际应用对于大多数程序员来说仍然是遥不可及。本书解释了何谓编程以及如何最佳化地使用它,为你在自己的工作中有效地使用模板编程提供了必备的基础。 本书瞄准于任何熟悉标准模板库(Standard Template Library,STL)惯用法的程序员。C++高级用户会获得对既有工作新的洞察以及对编程领域新的认知。那些已经学习了一些高级模板技术的中级程序员将会明白这些tricks是从哪儿适合大画面的,并将获得有秩序地使用它们所需的概念基础。对于那些已经嗅到编程味道但对其仍然感到神秘的程序员而言,最终将获得对编程如何工作、何时工作以及为何工作的清晰的理解。无论如何,所有读者都将获得一个可以自由支配的、威力空前的新工具:Boost Metaprogramming Library。 附赠光盘内容包含所有Boost C++ 程序库:Boost Metaprogramming Library及其参考文件,还包含所有随书代码示例以及大量的补充材料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值