How do I reliably static_assert on anything that isn't a string literal?
For example, in the following code, I've attempted to wrap the standard assert macro but statically reject anything for the message that's not a string literal (since anything but a string literal will not be displayed at runtime 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, the testing is done via the tests provided by the type_traits header, and, mostly, this code works as intended (tested with gcc 4.7.2). However, it doesn't specifically look for string literals as much as it just rejects common things that a programmer might use in place.
The solution I have may be good enough for the example above, but I'd like to use this, or a similar technique in other situations as well.
So the question is, how do I reliably use type_traits (or another standard mechanism) to static_assert on anything except a string literal?
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.