1
THE EXTREME DATABASE
WWW.QUASARDB.NET
2
MYTH: METAPROGRAMMING IS “USELESS”
3
Metaprogramming…
4
C++ 14…
5
Why metaprogramming?
6
Have the compiler generate the
correct program for you
• It knows things you don’t
• It will not be afraid to do tedious work
• It makes less mistakes than you
• Why write code when you could be
playing Baldur’s Gate 2 for the 10th
time?
Also: it’s awesome
A gentle introduction
7
int main(int argc, char ** argv)
{
static_assert(sizeof(int) == 4, "I want 32-bit integers!");
}
A more concrete example
8
#include <type_traits>
template <typename T>
T factorial(T v)
{
typedef typename std::integral_constant<T, 1> threshold;
static_assert(std::is_integral<T>::value, "I need an integral type");
return (v <= threshold::value) ? v : (v * factorial(v - 1));
}
A real metaprogram: compile time factorial
9
template <typename T, T v>
struct termination : std::conditional<v == 0, bool, void> {};
template <typename T, T v, typename Termination>
struct factorial_impl : std::integral_constant<T, v * factorial<T, v - 1>::type::value> {};
template <typename T, T v>
struct factorial_impl<T, v, bool> : std::integral_constant<T, 1> {};
template <typename T, T v, typename Termination = typename termination<T, v>::type>
struct factorial : factorial_impl<T, v, Termination> {};
10
C++ Metaprogramming :
Awesomeness overflow time
Also: typename.
The right code with tag dispatching
11
std::vector<int> v;
std::list<int> v;
template <typename Iterator>
void something_something_dark_side(Iterator first, Iterator last)
{
auto v = std::distance(first, last);
}
Wouldn’t it be cool to...
struct my_struct
{
int alpha;
std::string omega;
};
12
{
"my_struct" :
{
"alpha": 2,
"omega": "boom"
}
}
my_struct blah = { 2, ”boom” };
auto boom = json::generate(json::from_fusion(blah));
Introducing Boost.Fusion
13
BOOST_FUSION_ADAPT_STRUCT(my_struct, (int, alpha)(std::string, omega))
• Compile time introspection
• Bridge between compile time and runtime
Example, set of various types:
boost::fusion::set<struct1, struct2> blah;
boost::fusion::at_key<struct1>(blah);
LET’S BE EXTREME
14
”Perfect” serialization
15
Goals
• Generate correct code
• Allocate memory only if needed
• Generate highly optimized code
• No ”if mess”
• Unintrusive
• More time for Baldur’s Gate 2
Implementing serialization
template <>
struct codec<std::uint16_t, void>
{
template <typename OutIt>
static void encode(Outit & out,
boost::asio::mutable::buffer & sbuf, std::uint16_t i) {}
static boost::system::error_code decode(boost::asio::const_buffer & in,
std::uint_16_t & i) {}
};
template <>
struct scratch_size<std::uint16_t, void> :
boost::mpl::size_t<sizeof(std::uint16_t)> {};
16
Detect if alloc-free serialization is possible
17
struct static_size_tag { char pad; }; struct dynamic_size_tag { char pad[2]; };
template <typename T> struct is_static
{
template <typename U>
static static_size_tag dispatch(typename scratch_size<U>::type *) { return static_size_tag(); }
template <typename U> static dynamic_size_tag dispatch(...) { return dynamic_size_tag(); }
typedef is_static<T> type;
static const bool value = sizeof(dispatch<T>(nullptr)) == sizeof(static_size_tag);
};
The Metaprogrammer toolbox
18
• Clang 3.5+
• <type_traits>
• <tuples>
• Boost.MPL
• Boost.Fusion
• Boost.Hana - https://ldionne.github.io/hana/
MYTH: METAPROGRAMMING IS USELESS
19

C++ How I learned to stop worrying and love metaprogramming

  • 1.
  • 2.
  • 3.
    MYTH: METAPROGRAMMING IS“USELESS” 3
  • 4.
  • 5.
  • 6.
    Why metaprogramming? 6 Have thecompiler generate the correct program for you • It knows things you don’t • It will not be afraid to do tedious work • It makes less mistakes than you • Why write code when you could be playing Baldur’s Gate 2 for the 10th time? Also: it’s awesome
  • 7.
    A gentle introduction 7 intmain(int argc, char ** argv) { static_assert(sizeof(int) == 4, "I want 32-bit integers!"); }
  • 8.
    A more concreteexample 8 #include <type_traits> template <typename T> T factorial(T v) { typedef typename std::integral_constant<T, 1> threshold; static_assert(std::is_integral<T>::value, "I need an integral type"); return (v <= threshold::value) ? v : (v * factorial(v - 1)); }
  • 9.
    A real metaprogram:compile time factorial 9 template <typename T, T v> struct termination : std::conditional<v == 0, bool, void> {}; template <typename T, T v, typename Termination> struct factorial_impl : std::integral_constant<T, v * factorial<T, v - 1>::type::value> {}; template <typename T, T v> struct factorial_impl<T, v, bool> : std::integral_constant<T, 1> {}; template <typename T, T v, typename Termination = typename termination<T, v>::type> struct factorial : factorial_impl<T, v, Termination> {};
  • 10.
    10 C++ Metaprogramming : Awesomenessoverflow time Also: typename.
  • 11.
    The right codewith tag dispatching 11 std::vector<int> v; std::list<int> v; template <typename Iterator> void something_something_dark_side(Iterator first, Iterator last) { auto v = std::distance(first, last); }
  • 12.
    Wouldn’t it becool to... struct my_struct { int alpha; std::string omega; }; 12 { "my_struct" : { "alpha": 2, "omega": "boom" } } my_struct blah = { 2, ”boom” }; auto boom = json::generate(json::from_fusion(blah));
  • 13.
    Introducing Boost.Fusion 13 BOOST_FUSION_ADAPT_STRUCT(my_struct, (int,alpha)(std::string, omega)) • Compile time introspection • Bridge between compile time and runtime Example, set of various types: boost::fusion::set<struct1, struct2> blah; boost::fusion::at_key<struct1>(blah);
  • 14.
  • 15.
    ”Perfect” serialization 15 Goals • Generatecorrect code • Allocate memory only if needed • Generate highly optimized code • No ”if mess” • Unintrusive • More time for Baldur’s Gate 2
  • 16.
    Implementing serialization template <> structcodec<std::uint16_t, void> { template <typename OutIt> static void encode(Outit & out, boost::asio::mutable::buffer & sbuf, std::uint16_t i) {} static boost::system::error_code decode(boost::asio::const_buffer & in, std::uint_16_t & i) {} }; template <> struct scratch_size<std::uint16_t, void> : boost::mpl::size_t<sizeof(std::uint16_t)> {}; 16
  • 17.
    Detect if alloc-freeserialization is possible 17 struct static_size_tag { char pad; }; struct dynamic_size_tag { char pad[2]; }; template <typename T> struct is_static { template <typename U> static static_size_tag dispatch(typename scratch_size<U>::type *) { return static_size_tag(); } template <typename U> static dynamic_size_tag dispatch(...) { return dynamic_size_tag(); } typedef is_static<T> type; static const bool value = sizeof(dispatch<T>(nullptr)) == sizeof(static_size_tag); };
  • 18.
    The Metaprogrammer toolbox 18 •Clang 3.5+ • <type_traits> • <tuples> • Boost.MPL • Boost.Fusion • Boost.Hana - https://ldionne.github.io/hana/
  • 19.