How to define a string literal using type_traits?

How can I reliably static_assert on anything that is not a string literal?

For example, in the following code, I tried to wrap a standard assert macro, but statically rejected something for the message, not a string literal (since nothing but a string literal would be displayed at run time when the assert triggers).

#include <cassert> #include <string> #include <type_traits> #define my_assert(test, message)\ static_assert(\ (\ !std::is_pointer<decltype(message)>::value &&\ !std::is_array<decltype(message)>::value\ ),\ "literal string required"\ );\ assert((message, (test))); int main() { my_assert(1 == 1, "one equals one"); my_assert(1 == 2, "one equals two"); { const char *msg = "one equals one"; //my_assert(1 == 1, msg); // triggers static_assert } { const char msg[] = "one equals one"; //my_assert(1 == 1, msg); // triggers static_assert } { const std::string msg = "one equals one"; //my_assert(1 == 1, msg.c_str()); // triggers static_assert } { const int msg = 3; my_assert(1 == 1, msg); // should trigger static_assert } } 

As you can see, testing is done using the tests provided by the type_traits header, and basically this code works as intended (tested with gcc 4.7.2). However, he doesn’t specifically look for string literals, as he simply rejects common things that a programmer can use locally.

The solution I have may be good enough for the example above, but I would like to use this or a similar technique in other situations.

So the question is, how can I reliably use type_traits (or another standard mechanism) for static_assert for anything other than a string literal?

+6
c ++ c ++ 11 string-literals typetraits
source share
2 answers

Here is the best I can get that seems to reject everything that I throw at it, but accept literals anyway:

 #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 would be very interested to know if this is really correct, and / or if there is an easier way to make this detection.

+5
source share

'decltype ("some string")' of a string literal returns the type "const char (&) [n]". Thus, it seems that a shorter, in comparison with the following answer , method of its detection:

 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 )

0
source share

All Articles