我如何可靠地对任何不是字符串文字的东西进行static_assert?
例如,在下面的代码中,我试图包装标准的断言宏,但静态拒绝任何不是字符串文字的消息(因为当断言触发时,除了字符串文字之外的任何东西都不会在运行时显示).
#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 } }
如您所见,测试是通过type_traits标头提供的测试完成的,并且,
大多数情况下,此代码按预期工作(使用gcc 4.7.2测试).但是,它并不专门寻找字符串文字,因为它只是拒绝程序员可能使用的常见事物.
对于上面的例子,我所拥有的解决方案可能已经足够了,但我也想在其他情况下使用它或类似的技术.
所以问题是,除了字符串文字之外,我如何可靠地将type_traits(或其他标准机制)用于static_assert?
解决方法
这是我能得到的最好的,它似乎拒绝我抛出的任何东西,但仍然接受文字字符串:
#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)))
我很想知道这实际上是否完全正确,和/或是否有更简单的方法来进行此检测.