How to detect a string literal with type_traits?
'decltype("some string")' of a string literal returns "const char (&)[n]" type. Thus, it seems there is more succinct, in comparison with the following answer, way to detect it:
template<typename T>
struct IsStringLiteral :
std::is_same<
T,
std::add_lvalue_reference_t<const char[std::extent_v<std::remove_reference_t<T>>]>
>
{};
(online demo)
Note: it is possible to create a variable of const char (&)[n]
type which will fool this implementation:
const auto &msg1 = "some string";
const char c[4]{};
auto& msg2 = c;
// msg1 and msg2 is recognized by IsStringLiteral as string literals
static_assert(is_string_literal<decltype(msg1)>::value, "");
static_assert(is_string_literal<decltype(msg2)>::value, "");
Here is the best I could get, which appears to reject anything I throw at it, but still accepts literal strings:
#define my_assert(test, message)\
static_assert(\
(\
std::is_convertible <decltype(message), const char *>::value &&\
!std::is_rvalue_reference <decltype(message)>::value &&\
!std::is_pointer <decltype(message)>::value &&\
!std::is_array <decltype(message)>::value &&\
!std::is_class <decltype(message)>::value\
),\
"string literal required"\
);\
assert((message, (test)))
I'd be very interested to know if this actually is exhaustively correct, and/or if there is a simpler way to do this detection.