Constexpr cast to const char[]
It has happened to many people, and it happened to me. I got stuck playing with compile time strings in C++.
I decided to take the apparently unusable approach: using template <char...>
classes.
This is what I came up with, it is very common, nothing special, and also it does not work.
template <char... chars> class string
{
public:
static constexpr const char value[] = {chars...};
constexpr string()
{
}
constexpr operator decltype(value) & () const
{
return value;
}
};
template <char... chars> constexpr const char string <chars...> :: value[];
My idea was making a string
instance constexpr
constructible and exposing some kind of constexpr casting so that it would provide its content.
Now, if I do
static constexpr const char x[] = "ciao";
template <const char * str> void print()
{
std :: cout << str << std :: endl;
}
print <x> ();
This works and says ciao
. I get ciao
also if I do
std :: cout << string <'c', 'i', 'a', 'o'> {} << std :: endl;
or
print <string <'c', 'i', 'a', 'o', ' '> :: value> ();
But when I do
print <string <'c', 'i', 'a', 'o', ' '> {}> ();
I get: No matching function for call to print
.
I am definitely missing something. Is it unfeasible to do what I am trying to do? Making an instance do a constexpr cast to somehow return value
? If that worked, I would be able to easily make operators and string manipulation at compile time, the "only" downside being the ultra-boring 'i', 'n', 'i', 't', 'i', 'a', 'l', 'i', 'z', 'a', 't', 'i', 'o', 'n'
.
Further experiments
I did another experiment that works perfectly.
template <char... chars> class string
{
public:
constexpr string()
{
}
constexpr operator size_t () const
{
return sizeof...(chars);
}
};
template <size_t length> void print()
{
std :: cout << length << std :: endl;
}
print <string <'c', 'i', 'a', 'o'> {}> ();
And it prints out a pretty 4
.
In C++14, the restriction on template arguments to a template non-type parameter is:
A template-argument for a non-type, non-template template-parameter shall be one of:
* for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or
* the name of a non-type template-parameter; or
* a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as &
id-expression, where the id-expression is the name of an object or function, except that the &
may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
* a constant expression that evaluates to a null pointer value (4.10); or
* a constant expression that evaluates to a null member pointer value (4.11); or
* a pointer to member expressed as described in 5.3.1; or
* a constant expression of type std::nullptr_t
.
In your example, string<'c', 'i', 'a', 'o', '