Presentation is loading. Please wait.

Presentation is loading. Please wait.

6/3/2005C++ Template HENPC Group Meeting (LBNL)1 C++ Template Meta-Programming Igor A. Gaponenko (LBNL/NERSC)

Similar presentations


Presentation on theme: "6/3/2005C++ Template HENPC Group Meeting (LBNL)1 C++ Template Meta-Programming Igor A. Gaponenko (LBNL/NERSC)"— Presentation transcript:

1 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)1 C++ Template Meta-Programming Igor A. Gaponenko (LBNL/NERSC) IAGaponenko@lbl.gov

2 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)2 Contents What is the metaprogramming (MP) in general? –Definitions, applications, benefits… Why C++ (Template) MP? –What makes C++ “one of a kind” language for MP? The BOOST::MPL library –What’s actually inspired this talk Other most known C++ MP libraries –BOOTS::Type_traits –BOOST::Lambda –BOOST::Spirit –Blitz++ –FC++ –BOOST::Preprocessor (not a template MP!)

3 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)3 What is the metaprogramming? Metaprogram: –Literally: “a program about a program” –Actually: “a program that manipulates code” Major use of MP –Domain Specific Languages (DSL) Two types of DSL –DSL Translators (domain language != host one): C++ compiler & machine code Java compiler & byte code LEX/YACC: formal grammar rules into a compiler (in C) –Embedded DSL (EDSL) (domain language == subset of the host one): C++ Template MP Libraries(!) Functional programming is another use of MP –For mostly imperative languages like C++ (see references at the end of the talk)

4 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)4 Trivial Calculator Example: DSL vs EDSL 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 ‘)’ ; A “little language (calculator)” grammar in YACC (EBNF) to parse and evaluate arithmetic expression with the usual precedence rules: Yields a compiler which is able to translate: 123 - 44 3 * ( 2 + 1 )

5 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)5 Trivial Calculator Example: DSL vs EDSL (1) 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] >> ‘)’ ) ; The same grammar using BOOST::Spirit MP Library: Comments: 1.Each assignment stores a function object capable of parsing & evaluating a bit of grammar 2.A function object’s behavior is determined by a type of an expression used to construct the function object 3.A type of each expression is computed by a metaprogram associated with various (overloaded) operators used I still do NOT understand how it’s implemented!!! Before seeing this example I though I knew C++

6 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)6 General Benefits of EDSL MP Potentially faster programs –compile time optimization at the host language vs run-time optimization in generated YACC Deeper interaction with the target (host) language – an ability to mix domain and host languages in a natural way: –remember putting C++ constructs into YACC and shell commands into Make/Gmake? –no need to learn a new language –interacting with host language’s services (features & libraries) and other metaprograms is much smoother Yes, we can mix various EDSL-s within the same program! Maintainability (all-in-one) –No need to have a separate compiler (YACC-to-C) –No additional step to build and maintain that compiler The resulting compiler is the same program where the domain language is described (EBNF-alike language) In the end we’ll get a more expressive way to solve complex problems –Remember a delicate balance between: functionality, robustness and readability requirements when writing code!!!

7 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)7 Why C++ (Template) MP?... cout ::value << endl;... Take a look at this program: How it’s implemented (an oversimplified solution): // “Primary” template template struct binary { static unsigned const value = binary ::value << 1 | N%10; }; // Specialization to terminate recursion template<> struct binary { static unsigned const value = 0; }; 1.This program is at least “a number of bits” faster than its run-time version 2.It’s run-time safe (imagine passing “12223” as a parameter) 3.It’s an illustration of the “numeric computations” with C++ Templates MP

8 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)8 Why C++ (Template) MP? (1) // This trivial class supports the copy-by-value semantics class Copied { public: Copied(Copied const&); }; // A part of a complex hierarchy - can only be cloned class Cloned { private: Cloned(Cloned const&); public: virtual Cloned* clone() const; }; class DerivedFromCloned : public Cloned { }; // How to make a generic (type based) copy of these objects? Copied* cp = new Copied(...); Cloned* cl = new DerivedFromCloned(...); Copied* cp1 = GenericCopy<>( cp ); Cloned* cl1 = GenericCopy<>( cl ); Let’s consider the following problem (solution is on the next slide):

9 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)9 Why C++ (Template) MP? (2) #include // Two valiations of the helper function – the right one is chosen // at compile time. template T* GenericCopyImpl(T const* ptr) { return new T( &ptr ); } template T* GenericCopyImpl(T const* ptr) { return ptr->clone( ); } // The facility for end users template T* GenericCopy(T const* ptr) { return GenericCopyImpl ::value>( ptr ); } Here is a solution : 1.The right choice will be made at compile time 2.It’s an illustration of the “type computations” with C++ Templates MP 3.The boost::has_trivial_copy is a metafunction which operates on metadata (C++ types) and which returns its result in a form of another type convertible into a boolean value using ::value!!!

10 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)10 Why C++ (Template) MP? (3) Two above shown examples illustrate: –numeric computations with MP –type computations with MP …both done at compile time! So, why C++ is “one of a kind language” for MP? Because of its: –multi-paradigm heritage (a versatile and tunable language) –syntactic expressivity and run-time efficiency –static type system –near zero abstraction penalty (run-time polymorphism) –(!)mature compilers (as of today) and powerful optimizers that’s why MP is feasible today (not 10 years before)! The “performance” of the C++ Template MP-s can be measured in terms of a number of template instantiations! –a template system (parametric polymorphism) which can be used to: Generate new types and functions Perform (well, almost) arbitrary computations at compile time Dissect program components using BOOTS::Type_traits categorization –a macro preprocessor for MP at a textual level –48 built-in symbolic operators which can be overloaded with practically no limitations on a semantic of the operators

11 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)11 BOOST::MPL C++ Template MP is still a developing area –An ability to do MP in C++ was “almost accidentally discovered” around mid 90-th: Erwin Unruh, “Prime number computations”, 1994 Todd Veldhuizen, “Using C++ Template Metaprograms”, C++ Report, May 1995 No common standard (just yet? will ever be formulated?) MPL introduces its own model of MP (see next slides) MPL was (apparently) inspired by a success of STL MPL integrates with and uses other generic and MP libraries from BOOTS MPL complements STL

12 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)12 Definitions Metadata –are C++ types to be manipulated at compile time Integral constant wrappers – a special kind of metadata –To support numeric computations in MPL –To “store” (at compile time) an integral constant Metafunction –Is another central concept of MPL –It captures an idea of manipulation on metadata (types) –A metafunction has zero or more input types and it returns exactly one output type being a result of the manipulation on types Numerical metafunction – a special kind of metafunctions –To return values of numerical computations on input types (integral constant wrappers) Nullary metafunction –The one having zero input parameters

13 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)13 Metafunctions // A trivial example of a metafunction returning a pointer type template struct AddPointer { typedef typename T* type; }; // And here is how it can be used class MyClass { }; typedef AddPointer ::type MyClassPtr; MyClassPtr ptr = new MyClass(...); Examples of metafunctions : 1.At a surface it’s a useless class 2.However it illustrates an interface and use of metafunctions! 3.Input parameters are passed to metafunctions via a template list 4.The only output of the metafunction is a typ ereturned via the nested ::type definition

14 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)14 Integral Constants Wrappers // A trivial example of a wrapper struct Five { static int const value = 5; typedef int value_type; }; // A generic version template struct int_ { static int const value = N;... }; // A boolean template<> struct bool_ { static bool const value = true;... }; template<> struct bool_ { static bool const value = false;... }; typedef bool_ true_; typedef bool_ false_ ; The wrappers are meant to “store” constants in types : 1.The wrappers return stored values via the ::value member 2.They also return types of stored values via the ::value_type nested definition

15 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)15 Numerical Metafunctions // Given the above specified wrapper for integer constants we can implement // an operation for “adding” two numeric types template struct int_; template struct Add { typedef typename int_ type; }; // Using it... typedef int_ four; typedef int_ six; typedef Add ::type ten; cout << ten::value << “ Got 10?” << endl; Manipulate on integral constants wrappers : 1.Integral wrappers and numeric metafunctions are used in sequences and iterators 2.The same technique can also be used in dimensional analysis (white board illustration) to avoid mixing semantically(!) different types, even though they’re measured with the same type in C++

16 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)16 BOOST::type_traits Unlike artificial examples on previous slides this is an example of the useful MP library Is not part of BOOL::MPL –Though, developed based on the same philosophy and terminology –A powerful tool in a combination with MPL and STL Provides five groups of metafunctions –Primary Type Categorisation ::is_void ::is_class... Return integral wrappers around bool (::type::value) an a value itself (::value) –Secondary Type Categorisation ::is_arithmetic ::is_compoind … Return integral wrappers around bool –Type Properties ::is_const ::is_empty ::has_trivial_constructor … Return integral wrappers around bool –Relationships Between Types ::is_same ::is_convertible ::is_base_and_derived … Return integral wrappers around bool –Transformations Between Types ::remove_const ::add_reference … Return modified types (::type) See more information from here: –http://www.boost.org/libs/type_traits/index.htmlhttp://www.boost.org/libs/type_traits/index.html

17 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)17 More definitions Sequence –A collection of arbitrary types Iterator –To traverse elements of a sequence Algorithm –Is another name for a metafunction operating on a sequence Metafunction class –A class with a publicly accessible metafunction called ::apply –Passed as a sort of a function object (STL) to (meta-)algorithms View –An adaptor to a sequence (not to an iterator) –Unlike a sequence it supports a lazy instantiation

18 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)18 Sequences Sequences, iterators and algorithms are coupled together –MPL algorithms unlike STL-ones manipulate on sequences rather than on iterators!!! –There is great deal of similarity between MPL and STL Just keep in mind that we’re talking about compile time manipulations! Types of sequences: –Forward sequences mpl::vector mpl::list –Random access sequences mpl::vector –Associative sequences mpl::map mpl::set

19 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)19 Sequences and iterators : examples // Define a simple sequence of types class A; typedef mpl::vector Types; // Access elements of the vector using one step (NOTE: we’re passing a wrapper!) typedef mpl::at > CharPtr; // Access elements of seqeunces using iterators typedef mpl::begin ::type ItrBegin; ::BOOST_STATIC_ASSERT(( boost::is_same ::type>::value )); // Dereference the iterator to get the type (STL: T val = *itr;) typedef mpl::deref ::type Int; ::BOOST_STATIC_ASSERT(( boost::is_same ::value )); // Advance an iterator to the next type typedef mpl::deref ::type >>::type AnotherCharPtr; Iterators refer to elements of sequences:

20 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)20 Algorithms Operate on sequences (unlike STL ones) and are similar to STL ones Since input types (sequences) to algorithms are immutable then their results are returned as new types! May accept metafunction classes as “function objects” to manipulate the results Groups of algorithms: –Fundamental Sequence Algorithms (std::accumulate) mpl::fold –Quering algorithms mpl::find mpl::find_if … –Seqence Building Algorithms mpl::copy mpl::remove mpl::transform …

21 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)21 Algorithms : examples // Copy a list into a vector – will create a new type with a reversed order // of types. typedef mpl::list TypesList; typedef mpl::copy<TypesList, mpl::front_inserter > >::type TypesVector; // Make sure we got a vector with a reversed sequence of types ::BOOST_STATIC_ASSERT_NOT(( mpl::is_equal >::value )); Let’s reverse a sequence of types from a list into a vector: 1.An empty vector type is used as a seed to the mpl::from_inserter<> 2.The mpl::front_inserter<> used above is the metafunction class playing a role of a function object (binary operation) 3.An exact type of the mpl::copy<> algorithm may not be the same as mpl::vector, so we can’t use boost::is_same metafunction to compare them! However, both vectors should contain the same sequence of types, which we’re testing using the mpl::is_equal<> metafunction.

22 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)22 Views This concept is too difficult for the format of this talk –See MPL documentation for detail…

23 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)23 Crossing compile/run-time border with MPL That’s actually what MPL has been designed for A good (yet simple to explain) example to follow…

24 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)24 Other Most Known C++ (Template) MP Libs. BOOST::Lambda –The “lambda” idiom, which is famous in functional programming languages Java has the one too – remember code blocks used as event/signal handlers? BOOST::Blitz++ –One of the first successful MP libraries for C++ developed around 1995-th. –A (little) language to manipulate matrixes in a “natural” way –The amazing(!) “expression templates” programming idiom FC++ –Functional programming in C++ (for mathematicians and those whose brains are built the same way ) BOOST::Spirit –For defining EDSL parsers. Is based on EBNF-alike grammar description language –Also exploits another interesting functional programming idiom: “closure” (also known as “dynamic scoping”) BOOST::Preprocessor –MP on a text level using C/C++ preprocessor –Is used in the implementation of BOOST::MPL

25 6/3/2005C++ Template Meta-Programming @ HENPC Group Meeting (LBNL)25 BOOST::Lambda #include // Print elements of the array int a[5] = { 2, 4, 6, 8, 10 }; std::for_each( a, a+5, cout << _1, “, “ ); // Halve each element of the 2-d array int b[20][10] =...; std::for_each( a, a+5, for_loop(var(i)=0,var(i)<10,++var(i)) _1[var(i)] /= 2) ); Provides a mechanism for formulating compile time “lambda” expressions: 1.The “lambda” expression is an unnamed function 2.This is the lambda function: cout << _1, “, “ 3.The _1 is a “placeholder”, the “for_loop” and “var” are syntactical elements of the Lambda EDSL 4.This EDSL also supports “switch_statement.. case_statement.. default_statement”, etc.


Download ppt "6/3/2005C++ Template HENPC Group Meeting (LBNL)1 C++ Template Meta-Programming Igor A. Gaponenko (LBNL/NERSC)"

Similar presentations


Ads by Google