Embedded Declarative HTML in C++

Lublin, 2011-11-20

Here’s for some crazy C++:

Node html
{"html", {{ "lang", "pl" }}, { // tag with attributes
  {"head", { // tag without attributes
    {"title", {
      "Page Title" // text node
    }}
  }},
  {"body", {{ "style", "background-color: #fff;" }}, {
    {"h1", {"Page Title"}},
    {"div", {}} // empty tag
  }}
}};

cout << html;

that’s giving us this:

<html lang="pl">
  <head>
    <title>
      Page Title
    </title>
  </head>
  <body style="background-color: #fff;">
    <h1>
      Page Title
    </h1>
    <div />
  </body>
</html>

Inspired by Hiccup and a slide in a presentation on Kotlin language, I wanted to try something like this with the newest bits of C++11.

std::initializer_list

C++11 introduced the std::initializer_list type which is a neat enhancement to C’s intializer lists. C’s initializer lists are a way for creating arrays and structs:

int array[] = { 1, 2, 3 };
struct { float a, b; } number = { 0, -1 };

C++’s std::initializer_list is a clever enhancement because it’s a runtime object which knows how many elements are in it and those elements are created automatically by the compiler. It’s useful in functions and constructors when you want to pass some inline data structures, for example a function:

int sum(initializer_list<int> numbers) {
  int s = 0;
  // a proper foreach is also a C++11 feature
  for (const int i : numbers) {
    s += i;
  }
  return s;
}

could be used like:

sum({1, 2, 3, 4});

New implementations of STL containers (such as vectors) support that in constructors so you can fill them with data in construction time:

vector<int> nums {1, 2, 3};

Proof’O’Concept

In my humble proof of concept I just extended the use of std::initializer_list. Each node in tree is either:

For each variant there’s a different constructor. That’s pretty much it. The source code is in this gist. Probably the longest and least interesting part is the render method, but somewhat obligatory to see if the whole thing works at all.

Without macros!

In C++11, solution is straight-forward and maybe even handsome but I am most curious how it could be done in older versions of C++. I think that initializer_lists and other new features of C++11 (lambdas!) made it possible to create more sophisticated internal DSLs than the one presented here. Maybe even something like GUI FTW.

(source code)