Being able to create and manipulate strings during compile-time in C++ has several useful applications. Although it is possible to create compile-time strings in C++, the process is very cumbersome, as the string needs to be declared as a variadic sequence of characters, e.g.
using str = sequence<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!'>;
Operations such as string concatenation, substring extraction, and many others, can easily be implemented as operations on sequences of characters. Is it possible to declare compile-time strings more conveniently? If not, is there a proposal in the works that would allow for convenient declaration of compile-time strings?
Why Existing Approaches Fail
Ideally, we would like to be able to declare compile-time strings as follows:
// Approach 1
using str1 = sequence<"Hello, world!">;
or, using user-defined literals,
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
where decltype(str2)
would have a constexpr
constructor. A messier version of approach 1 is possible to implement, taking advantage of the fact that you can do the following:
template <unsigned Size, const char Array[Size]>
struct foo;
However, the array would need to have external linkage, so to get approach 1 to work, we would have to write something like this:
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string<13, str>;
return 0;
}
Needless to say, this is very inconvenient. Approach 2 is actually not possible to implement. If we were to declare a (constexpr
) literal operator, then how would we specify the return type? Since we need the operator to return a variadic sequence of characters, so we would need to use the const char*
parameter to specify the return type:
constexpr auto
operator"" _s(const char* s, size_t n) -> /* Some metafunction using `s` */
This results in a compile error, because s
is not a constexpr
. Trying to work around this by doing the following does not help much.
template <char... Ts>
constexpr sequence<Ts...> operator"" _s() { return {}; }
The standard dictates that this specific literal operator form is reserved for integer and floating-point types. While 123_s
would work, abc_s
would not. What if we ditch user-defined literals altogether, and just use a regular constexpr
function?
template <unsigned Size>
constexpr auto
string(const char (&array)[Size]) -> /* Some metafunction using `array` */
As before, we run into the problem that the array, now a parameter to the constexpr
function, is itself no longer a constexpr
type.
I believe it should be possible to define a C preprocessor macro that takes a string and the size of the string as arguments, and returns a sequence consisting of the characters in the string (using BOOST_PP_FOR
, stringification, array subscripts, and the like). However, I do not have the time (or enough interest) to implement such a macro =)
Question&Answers:
os