Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming -...

54
C++ Template Metaprogramming Practical Approach code::dive 2016 Szymon Gutaj

Transcript of Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming -...

Page 1: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

C++ Template MetaprogrammingPractical Approach

code::dive 2016Szymon Gutaj

Page 2: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach2

In brief

● Introduction● Metaprogramming techniques● Questions / Discussion

Page 3: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach3

Introduction

Page 4: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach4

(My Humble) Definition

Shifting complexity from the user/client sideto the library/compiler side

Augmenting the compiler

Page 5: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach5

Aims

● Correctness (reducing human factor)– By generating code according to (tested) rules– By introspecting and checking code at compile time– By creating libraries smarter than their user– By avoiding repetition

Page 6: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach6

Aims

● Performance (self-optimisation)– By performing things at compile time– By generating fine-tuned code in particular situation– By performing optimisations cumbersome to handcraf

Page 7: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach7

Aims

● Portability (self-adaptability)– By automatically adapting to current hardware– By intelligently picking optimal code blocks– By keeping all code in the C++ realm

Page 8: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach8

Aims

● Expressive interfaces– By automatically deducing details for the user– By creating domain-specific languages

Page 9: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach9

Consequences (wink)

● You'll keep your job forever, having written metaprogrammed code(if your colleagues like you)

● You'll be happy to have trained karate for 15 years(if they don't like you)

● Nothing will happen (are you sure, that anyone has seen your commit?)

Page 10: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach10

Consequences

● Development time of your (metaprogrammed) librarydepends on skill and tools used

● Maintenance of your library requires some skill● Your user code becomes higher level● Your user code becomes smaller and more declarative● Changes to your library (bugfixes and new features)

propagate to all places of usage

Page 11: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach11

Approaches

● Handcrafted● With aid of C++ Standard Library (type_traits)● With aid of Boost (Boost Metaprogramming Library, Boost Hana)● With aid of higher level, domain-specific libraries

Page 12: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach12

How it works

● C++ Metaprogramming is purely functional● Mutation is replaced with copying (with changes applied)● Iteration is replaced with recursion● Computational complexity of a metaprogram is measured with the

amount of template instantiations (copies)

Page 13: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach13

Golden rules

● Keep your code orthogonal● Keep your conventions consistent● Solve things by adding one more level of indirection

Page 14: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach14

Handcrafed metaprogrammingBasics and conventions

Page 15: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach15

Disclaimer

Our examples are meant to be fun, easy and demonstrational

Page 16: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach16

Hello world!

1 // This is our metaprogram (actually quite useful!)2 template<typename T>3 struct return_as_is4 {5 typedef T type;6 };7 8 // This is our processed data9 class HelloWorld10 {11 };12 13 // What is the type of ‘helloWorld’? Yes, it’s HelloWorld!!!14 return_as_is<HelloWorld>::type helloWorld;

Page 17: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach17

Operating on types

● Template name is the operation name● Template parameters are the arguments● Nested definition named “type” is the result● The “struct” keyword is used to keep the syntax clean● We've just described a metafunction!

Page 18: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach18

Operating on types

1 // Adds a pointer to given type2 template<typename T>3 struct add_pointer4 {5 typedef T * type;6 };7 8 // ‘pointerToInt’ is of type ‘int *’9 add_pointer<int>::type pointerToInt {nullptr};

Page 19: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach19

Operating on values

● Template name is the operation name● Template parameters are the arguments● Nested member named “value” is the result● Nested member is static const / constepxr

Page 20: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach20

Operating on values

1 // Increments given value by one2 template<int V>3 struct increment4 {5 static constexpr int value = V + 1;6 };7 8 // Variable ‘four’ equals 49 // ‘3 + 1’ happened during compilation10 int four = increment<3>::value;

Page 21: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach21

Operating on values

1 // Wraps an integer in a type2 template<3 typename T,4 T Value5 >6 struct integral_constant 7 {8 typedef integral_constant type;9 10 static constexpr T value = Value;11 };12 13 // Dressing values as types can be useful14 typedef integral_constant<int, 1> one;15 typedef integral_constant<int, 2> two;

Page 22: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach22

Simple processing

● Pattern matching is used for “flow control”● Patterns are defined with partial template spacialisations

Page 23: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach23

Simple processing1  template< // Primary template: “true” case2      bool Condition,3      typename TrueType,4      typename FalseType5  >6  struct if_7  {8      typedef TrueType type; // TrueType is the result9  };10  11 template< // Partially specialised: “false” case12     typename TrueType,13     typename FalseType14 >15 struct if_<false, TrueType, FalseType>16 {17     typedef FalseType type; // FalseType is the result18 };

Page 24: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach24

Simple processing#include <cstdint> // For INT8_MAX, int8_t and int_least16_t

#include "wild_wild_world/constants.h" // SOME_CONSTANT comes from here

typedef if_<    (SOME_CONSTANT < INT8_MAX),    int8_t,    int_least16_t>::type smallest_type;

// ‘myConstant’ has the smallest type, that fits the valuesmallest_type myConstant = SOME_CONSTANT;

Page 25: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach25

Simple processing

1  #include "configuration.h" // For WANT_SPEED2  #include "algorithm_speedy.h" // For algorithm_speedy3  #include "algorithm_tiny.h" // For algorithm_tiny4  5  typedef if_<6      WANT_SPEED,7      algorithm_speedy,8      algorithm_tiny9  >::type algorithm;10  11 algorithm a;12 13 a.run(); // Runs the selected algorithm

Page 26: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach26

Simple recursion

● Pattern matching with a “terminal case” allow for recursion● Patterns are defined with partial template spacialisations

Page 27: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach27

Simple recursion1  template<typename T>2  struct rank // Terminal case: T is not a table anymore3  {4      static constexpr int value = 0;5  };6  template<typename T, int N>7  struct rank<T[N]> // Case: T is a table8  {9      static constexpr int value = rank<T>::value + 1;10 };11 template<typename T>12 struct rank<T[]> // Case: T is a table (of unknown size)13 {14     static constexpr int value = rank<T>::value + 1;15 };16 auto rank0 = rank<std::string>::value; // Equals 017 auto rank1 = rank<int[2][4]>::value;   // Equals 218 auto rank2 = rank<int[4][3][]>::value; // Equals 3

Page 28: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach28

Metafunction forwarding

● Inheritance is a neat way to compose metaprograms● Code and conventions are automatically propagated

Page 29: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach29

Metafunction forwarding

1  // ‘false_type’ is an alias for ‘bool’ equal ‘false’2  struct false_type :3      integral_constant<4          bool,5          false,6      > {};7  8  // ‘true_type’ is an alias for ‘bool’ equal ‘true’9  struct true_type :10     integral_constant<11         bool,12         true,13     > {};

Page 30: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach30

Metafunction forwarding

1  template<typename T>2  struct is_byte_sized :3      if_<4          (sizeof(T) == 1),5          true_type,6          false_type7      > {};8  9  bool byteSized = is_byte_sized<char>::value; // true1011 bool notByteSized = is_byte_sized<int>::value; // false

Page 31: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach31

Lazy evaluation

● Lazy evaluation gives more flexibility● Invalid, but unneeded branches of code still compile● Lazy evaluation leads to faster code● Stay lazy, whenever you can

Page 32: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach32

Lazy evaluation

1  // Eager!!!2  template<typename T>3  struct my_favourite :4      if_<5          is_good_enough<T>::value,6          take_it<T>::type, // 'take_it' always evaluated7          fix_it<T>::type // 'fix_it' always evaluated8      > {};9  10 // Lazy...11 template<typename T>12 struct my_favourite :13     if_<14         is_good_enough<T>::value,15         take_it<T>, // 'take_it' evaluated for ‘true’16         fix_it<T> // 'fix_it' evaluated for ‘false’17     >::type {};

Page 33: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach33

Toolset

● Compile-time operators are the low-level means for code introspection– sizeof, decltype, alignof, ternary operator, template template parameters, ...

● Language rules are your worst enemy and best friend– resolution/conversion rules, SFINAE, variadic templates, ...

Page 34: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach34

Toolset

1  struct NeighbourRomek // A well behaved guy2  {3      void howdy();4  };5  6  struct ManInBlack // Well, who knows...7  {8  };9  10 // Let’s check contents of some types11 bool doesnt = has_howdy<int>::value; // false12  13 bool does = has_howdy<NeighbourRomek>::value; // true14  15 bool afraidToCheck = has_howdy<ManInBlack>::value; // ?!

Page 35: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach35

Toolset

1  template<typename T, void(T::*)() = &T::howdy>2  char hasHowdy(int); // Helper: SFINAE sensitive3  4  template<typename T>5  long hasHowdy(...); // Helper: less sensitive6  7  // Returns ‘true’ if ‘T’ has a member function ‘howdy’8  template<typename T>9  struct has_howdy :10     integral_constant<11         bool,12         sizeof(char) == sizeof(hasHowdy<T>(0))13     > {};

Page 36: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach36

Toolset

1  template<typename T> // Helper: matches a pointer 2  true_type hasHowdy(decltype(&T::howdy));3  4  template<typename T>5  false_type hasHowdy(...); // Helper: matches everything6  7  // Returns ‘true’ if ‘T’ has a member function ‘howdy’8  template<typename T>9  struct has_howdy :10     decltype(hasHowdy<T>(nullptr))11 {};

Page 37: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach37

Homework

● Metafunction classes (first step to passing metafunctions around)● Higher order metafunctions (composed metafunctions)● Tag based dispatch (adding a second level of abstraction)● Variadic template parameter pack access (very useful)

Page 38: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach38

Asertive code

● Assertive code makes error messages better● Assertive code prevents abuse of your metaprogram● Use “static_assert”● Use “std::is_same” or alike● Wait for a standardised C++ feature: concepts!

Page 39: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach39

Testing

● Can be done in a regular cpp file● Compile that file with your code for early testing

Page 40: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach40

Testing

1  #include <type_traits>2  #include "pass_optimally.h" // Code under test34  static_assert( // Test case 15      std::is_same< // More on ‘std::is_same’ in a minute6          pass_optimally<VeryBigClass>::type,7          VeryBigClass const &8      >::value,9      "Expected passing large arguments by reference"10 );11 static_assert( // Test case 212     std::is_same<13         pass_optimally<int>::type,14         int15     >::value,16     "Expected passing small arguments by value"17 );

Page 41: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach41

Asertive code

1  template<class Agent, class Handler, class ...Args>2  void Base::call(Handler Agent::*handler, Args&&... args)3  {4      static_assert( // Check if calculated ‘handler’ and ‘args’ match5          std::is_constructible< // More on this in a second6              void(Agent::*)(Args...),7              decltype(handler)8          >::value,9          "Calling with bad arguments."10         "Args need to match the signature of Handler"11     );12     call(std::bind( // If assertion passed, make the call13         handler,14         static_cast<Agent * const>(this),15         std::forward<Args>(args)...)16     );17 }

Page 42: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach42

Standard Template Librarytype_traits

Page 43: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach43

Features

● Basic type instrospection:– is_integral, is_pointer, is_function, is_class, ...– is_same, is_base_of, is_move_constructible, is_convertible,

has_virtual_destructor, ...● Basic type processing:

– add_cv, remove_reference, make_signed, ...● Basic metaprogramming facilities:

– conditional, integral_constant, enable_if, result_of, ...

Page 44: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach44

Example – type_traits

1  #include <type_traits>2  // Return ‘as is’ for unsigned types3  template<typename T>4  typename std::enable_if<5      std::is_unsigned<T>::value, // The condition6      T                           // The return type7  >::type alwaysPositive(T t) { return t; }8  9  // Return absolute and unsigned10 template<typename T> 11 typename std::enable_if<12     !std::is_unsigned<T>::value, // The condition13     typename std::make_unsigned<T>::type // The return type14 >::type alwaysPositive(T t)15 {16    return (t < 0) ? ­t : t;17 }

Page 45: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach45

Boost Metaprogramming LibraryBoost MPL

Page 46: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach46

Features

● Mimicks C++ STL features at compile time● Containers and views:

– vector, list, map, set, string, ...● Algorithms:

– fold, transform, sort, copy, find, count, partition, ...● Functional processing (including higher order):

– lambda, quote, bind, apply, if_, ...● Basic metafunctions:

– and_, or_, not_, bitand_, less, min, ...● Basic runtime interfacing:

– for_each, c_str, ...

Page 47: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach47

Example – Boost MPL

1  tuple<int, char const*, bool> myTuple; // Poor man’s tuple2  get<int>(myTuple) = 123; // Access elements by type3  get<char const*>(myTuple) = "hello";45  // (Implementation) Holds a tuple element of type T6  template<typename T>7  struct tuple_field8  {9      T field;10 };1112 // (Implementation) Accesses a tuple element by type13 template<typename T>14 T & get(tuple_field<T> & t)15 {16    return t.field;17 }

Page 48: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach48

Example – Boost MPL

1  #include <boost/mpl/empty_base.hpp>2  #include <boost/mpl/fold.hpp>3  #include <boost/mpl/inherit.hpp>4  #include <boost/mpl/placeholders.hpp>5  #include <boost/mpl/vector.hpp>67  using namespace boost;8  using namespace boost::mpl::placeholders;910 // Composes a tuple, inheriting tuple_field’s11 template<typename ...Fields>12 struct tuple :13     mpl::fold< // The algoritm: fold/accumulate14         mpl::vector<Fields...>,           // The data15         mpl::empty_base,                  // The initial value16         mpl::inherit<_1, tuple_field<_2>> // The operation17     >::type {};

Page 49: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach49

Boost Hana

Page 50: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach50

Features

● Can do compile-time computation (like Boost MPL)● Can do runtime computation (like STL)● Can do heterogeneous computation (like Boost Fusion)● Requires a (decent) C++14 compiler

Page 51: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach51

Example – Boost Hana

1  #include <boost/hana.hpp>2  using namespace boost;3  struct Fish { std::string name; };4  struct Cat  { std::string name; };5  struct Dog  { std::string name; };67  auto animals = hana::make_tuple(8      Fish{"Nemo"}, Cat{"Garfield"}, Dog{"Snoopy"}9  );10 // Applies a (heterogenous) algorithm in runtime11 auto names = hana::transform(animals, [](auto a) {12     return a.name;13 });1415 assert(hana::reverse(names) ==16     hana::make_tuple("Snoopy", "Garfield", "Nemo")17 );

Page 52: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach52

Example – Boost Hana

1  auto animal_types = hana::make_tuple(2     hana::type_c<Fish*>,3     hana::type_c<Cat&>,4     hana::type_c<Dog*>5  );6  // Applies an algorithm in compile time7  auto animal_ptrs = hana::filter(animal_types, [](auto a) {8      return hana::traits::is_pointer(a);9  });1011 static_assert(animal_ptrs == hana::make_tuple(12     hana::type_c<Fish*>, hana::type_c<Dog*>), ""13 );

Page 53: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach53

Thank you!

Page 54: Template Metaprogramming - Practical Approach · code::dive 2016 - C++ Template Metaprogramming - Practical Approach 10 Consequences Development time of your (metaprogrammed) library

code::dive 2016 - C++ Template Metaprogramming - Practical Approach54

Questions?