In C 20 it is possible to write a wrapper class which only accepts string literals.
struct string_literal
{
template<size_t N>
consteval Wrapper(char const (&s)[N]) : p(s) {}
char const* p;
};
void takes_literal(string_literal lit) {
// use lit.p here
}
from OP's own answer here https://stackoverflow.com/a/74922953
Is it also possible to write a concept that only matches string literals?
CodePudding user response:
A char const*
which points into a string literal is virtually no different from any other char const*
. The fact that a literal starts its life as an array is irrelevant, as non-literal character arrays can also be created. To my knowledge, there is exactly one difference: pointers to string literals cannot be used as non-type template parameters.
That's not particularly helpful. Even if we were restricted to compile-time code execution, you can get non-literal char const*
s which also cannot be used as NTTPs (by creating a std::string
, which can now be done at compile-time. You can call constexpr
functions on string::c_str
s pointer, but you can't use the result as an NTTP).
The best you can do is to create a user-defined literal operator that returns your string_literal
object. You can make it so that only this literal operator can construct such a type (besides copying, of course). But even then, they can call your operator""
directly with a non-literal, and there is nothing you can do about it.
Instead, you should re-evaluate why you need to know if it is a string literal specifically.
CodePudding user response:
Whereas const char(&)[N]
isn't necessary a string literal, you might create concept to match const char(&)[N]
:
template <typename T>
struct is_str_literal_impl : std::false_type{};
template <std::size_t N>
struct is_str_literal_impl<const char[N]> : std::true_type{};
template <typename T>
concept concept_str_literal = is_str_literal_impl<T>::value;
void takes_literal(concept_str_literal auto& lit) {
// use lit.p here
}