如何对任何非字符串文字的内容进行可靠的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?
答案 0 :(得分:7)
这是我能得到的最好的,它似乎拒绝我抛出的任何东西,但仍然接受文字字符串:
#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)))
我非常有兴趣知道这个实际是否完全正确,和/或是否有更简单的方法来进行此检测。
答案 1 :(得分:0)
&#39; decltype(&#34;某些字符串&#34;)&#39;字符串文字返回&#34; const char(&amp;)[n]&#34;类型。 因此,与the following answer相比,似乎有更简洁的方法来检测它:
template<typename T>
struct IsStringLiteral :
std::is_same<
T,
std::add_lvalue_reference_t<const char[std::extent_v<std::remove_reference_t<T>>]>
>
{};