Embedded Declarative HTML in C++

How about writing that in 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;

and getting that:

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

Clojure has the Hiccup and Groovy has it's builders for XML/HTML generation. I saw today a presentation with an example of this in Kotlin, with static typing...

I wanted to see if something like this is possible in C++. It turned out that with help of some newest and freshest stuff in C++11 it was pretty straight-forward.

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 an runtime object which knows how many elements are in it and are created automatically by the compiler. It's useful in functions and constructors when you want to pass some inlined 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. I've pasted a complete gist at the end of this article. 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. I actually believe it is now possible to implement something like GUI FTW in C++.

The source code will probaly not be embedded in RSS reader. Read it on my site or on gist.github.com.

blog comments powered by Disqus