Recently I stumbled upon a question by @arne_mertz of Simplify C++ fame (if you don't read that blog, start now!) about using string literals as types. In 2013 I wrote about strings as types, and the technique used works, but it's not exactly elegant.
The problem is to get from "string literal", to something like
This, it turns out, is not very easy.
C±±11 gave us constexpr functions, and C++14 added some helpful utilities like integer_sequence<>, and from there you may think code like the below would do the trick.
Unfortunately things aren't that simple. Although make_string() is constexpr, the parameter array loses its constexpr property in the function, so operator does not give a constexpr result, and thus String<array[I]...> is ill formed and gives a compilation error.
A possible way to get around that, is to let the macro create and call a lambda, and have the lambda contain the string literal.
Looking into the crystal ball, we see C++17 offering constexpr lambdas, and that gives an opening.
The idea is that string_builder() calls the lambda for each index in the std::index_sequence<> from 0 to the length of the string literal. The constexpr lambda returns the character in position i of the string literal.
A possible implementation of string_builder() is
This almost seems like magic, but it's not that weird. f is the constexpr lambda that returns a char for a position in the string literal. I... are all indexes from 0 to sizeof the string literal. Since f is constexpr, String<f(I)...> is well formed.
So, what's the cost of doing this? Well, the cost is build time. Runtime has no overhead compared to a fixed string global somewhere.
Look at this example:
Using clang++ (svn trunk on 2016-08-25) the output from clang++ -std=c++1z str.cpp -O1 -S is
The above is perhaps not obvious, but at line 12, the address to the beginning of String<>::buffer is stored in register edi, in preparation for the function call on line 13.
Line 25 shows that the buffer is the string "nonsense".
So, there is no run time overhead what so ever. However, each unique string used is its own symbol, which may increase link time, and the compile time computation required to get the string from the string, is of course not for free.