ivan100sic's blog

By ivan100sic, history, 3 years ago, In English

Take a look at this snippet:

#include <iostream>
#include <string>
using namespace std;

template<const char* tag>
struct html_element {
  string s;

  template<typename... Args>
  html_element(Args... args) : s((... + (string)args)) {}

  operator string() { return string("<") + tag + ">" + s + "</" + tag + ">"; }
};

const char html_c[] = "html";
const char body_c[] = "body";
const char h2_c[] = "h2";

using html = html_element<html_c>;
using body = html_element<body_c>;
using h2 = html_element<h2_c>;

int main() {
  string doc{
    html{
      body{
        h2{ "hello" },
        h2{ "world" }
      }
    }
  };

  cout << doc << '\n';
}

Thank you for your attention

  • Vote: I like it
  • +204
  • Vote: I do not like it

»
3 years ago, # |
  Vote: I like it -36 Vote: I do not like it

That definitely looks like Reactjs or something similar to me

»
3 years ago, # |
  Vote: I like it +27 Vote: I do not like it

May I direct your attention to https://github.com/csb6/html-plus-plus

»
3 years ago, # |
Rev. 2   Vote: I like it +5 Vote: I do not like it

What will happen in this code if you want to use "img" in html?

»
3 years ago, # |
  Vote: I like it +6 Vote: I do not like it

is this some kind of peasant joke im not able to understand

»
3 years ago, # |
Rev. 2   Vote: I like it -13 Vote: I do not like it

There is also the crow framework for proper web development in C++. LinkedIn has a good course for it.

»
3 years ago, # |
  Vote: I like it +10 Vote: I do not like it

Unpopular opinion: C++ is both the best and the worst language, for any purpose.

Okay, this does like awesome at first but then you find out you miss a couple of things that make this code terribly inefficient. For example:

template<typename... Args> html_element(Args... args) : s((... + (string)args)) {}

This invokes copy constructor of args which may be inefficient. Or maybe not, if copy elision takes place. Either way you probably don't want to hope it works as you expect it to, so you should probably add a universal reference. Also this is going to break if args is empty, and I wouldn't recommend C-style cast, and you should perfect-forward arguments, something like this:

template<typename... Args> html_element(Args&&... args) : s((""s + ... + std::forward<Args>(args))) {}

Then, you most likely want to construct HTML in-place and not copy it here and there, so you may think it's a good idea to make std::string take this via an rvalue reference:

operator string() && { return string("<") + tag + ">" + std::move(s) + "</" + tag + ">"; }

This code may look fine but it still involves copying because a big string is still constructed every time via concatenation. You may think a std::string_stream would work well:

template<typename Stream, const char* tag> Stream& operator<<(Stream& ss, const html_element<tag>& element) { return ss << "<" << tag << ">" << element.s << "</" << tag << ">"; }

But you'd still have std::string s member which would ruin performance. Honestly I have no idea how to fix this except resorting to slow-compilation compile-time template-based strings. Or just using a template compiler instead, which you should be using anyway.


Disclaimer: I haven't tried to compile any of these codes.