C++ metaprogramming
-
Upload
arindam-mukherjee -
Category
Software
-
view
161 -
download
4
Transcript of C++ metaprogramming
C++TEMPLATE METAPROGRAMMING
Arindam MukherjeePune C++ and Boost Meetup
Template type computations
Templates provide a Turing complete computation subsystem – that runs during compilation.
This capability was not entirely consciously designed.
Erwin Unruh found this somewhat accidentally ~ early 90s.
Templates
Compile time entities completely evaluated by the compiler, based on arguments passed.
std::vector<int> nums; // std::vector<int> unrelatedstd::vector<std::string> names; // to std::vector<std::string>
template <typename T> class Foo; // declaration
template <typename T> class Foo { … }; // definitionFoo<int> foonum; // Foo<int> is specialization
Non-type template parameters
Templates can have non-type parameters:template <typename T, int N>struct array {
T data[N];….
}
Non-type args are compile time constants.array<int, 10> arr; // array of 10 ints
sizeof is evaluated at compile time.int arr[sizeof(int)]; // array of 4* ints
Embedded types
Typedefs inside a class / class template.template <typename T>struct add_const {
typedef const T type;};
add_const<int>::type ci; // const int
Embedded constants
Enums inside a class / class template.template <int M, int N> struct add {
enum { value = M + N }}
int array[add<10, 20>::value];
Branching: specializations
Specialize for specific types.template <typename T>struct Foo { … }; // default impl
template <>struct Foo<int> { … }; // int-specific
Applicable to function templates too.
Partial specializations
Specialize for type families.template <typename T, typename U>struct Foo { … }; // default impl
template <typename T>struct Foo<T, T> { … }; // Foo<char, char>
template <typename T>struct Foo<T*, T> { … }; // Foo<int*, int>
NOT applicable to function templates.
Recursion by specializations
Compute factorial at compile time:template <int N> struct factorial {enum { value = N*factorial<N-1>::value };};
template <> struct factorial<0> { // terminating condition
enum { value = 1 };};
Applying the techniques
Remove const:template <typename T> struct remove_const{ typedef T type; };
template <typename T> // partialstruct remove_const<const T> { // speclzn
typedef T type;};
Called as:remove_const<const int>::type x; // int
Applying the techniques
Querying types:template <typename T, typename U>struct are_same{ enum { value = 0 }; };
template <typename T> / partialstruct are_same<T, T> // specialization{ enum { value = 1 }; };
Called as:are_same<int, int>::value == 1;
Applying the techniques
Remove levels of indirection:template <typename T>struct deref{ typedef T type; };
template <typename T> // partialstruct deref<T*> { // specialization
typedef typename deref<T>::type type; }
Called as:deref<int*****>::type x; // x is int
Boost Type Traits
A header-only library to query and manipulate types at compile time.
Lots of trait metafunctions.#include <boost/type_traits.hpp>
typedef int* intptr;assert(boost::is_ptr<intptr>::value);
struct Foo {int a; void *b; float c; };assert(boost::is_pod<Foo>::value);
SFINAE
Compiler tries to resolve function calls to a unique overload, or unique template with appropriate arguments.
Multiple templates may be candidates but a unique one must survive.
All candidates instantiated.
Those that fail instantiation eliminated. Not An Error if a single candidate survives.
SFINAE & enable_if
Exploit SFINAE to resolve to apt template.
boost::enable_if#include <boost/utility/enable_if.hpp>
boost::enable_if<true, T>::type x; // Tboost::enable_if<false, T>::type y; //!def
boost::disable_if (opposite of enable_if).
SFINAE & enable_if (contd.)
Serialize arbitrary types:#include <boost/utility/enable_if.hpp>typedef vector<char> buffer_t;template <typename T>buffer_t serialize(const T&);
Need a fast version for POD types and generic version for non-POD types.template <typename T>enable_if<is_pod<T>, vector<char>>::typeserialize(const T&) {…} // pod version// Use disable_if for the non-POD version
Metafunctions
Metafunction: a class or class template taking only type parameters, with a single embedded typedef.
All the Boost type traits are metafunctions.
Boost TMP Library: library of metafunctions.
Provides means of composing and generating metafunctions from simpler metafunctions.
Composing metafunctions
Metafunctions need to be combined:#include <boost/type_traits.hpp>
template <typename T> void foo(T obj) {if (boost::is_pointer<T>::value ||
boost::is_array<T>::value) //runtime{ … }else { … }
}
Boost MPL (contd.)
How to make another metafunction that OR’s two type traits.#include <boost/mpl/or.hpp>#include <boost/type_traits.hpp>
template <typename T> void foo(T obj) {if (boost::mpl::or_<
boost::is_pointer<T>, boost::is_array<T>
>::value){ … }else { … }
}
Boost MPL (contd.)
Numbers can be wrapped in types:#include <boost/mpl/integral_c.hpp>#include <boost/mpl/greater.hpp>#include <boost/type_traits.hpp>
namespace mpl = boost::mpl;template <typename T, typename U>struct is_larger : mpl::greater<
mpl::integral_c<size_t, sizeof T>, mpl::integral_c<size_t, sizeof U>>
{};
Thank you!
Q & A
Book: Modern C++ Design – Andrei Alexandrescu
Book: Advanced C++ Template Metaprogramming – Davide di Gennaro
Book: C++ Template Metaprogramming –Dave Abrahams, Aleksey Gurtovoy