我正在尝试创建一个静态断言其参数是一个严格正的int的宏。这适用于我的许多其他遗留宏,到目前为止,它们只是假设没有检查其参数的完整性。
简而言之,如果我有一个条目,我想要传递static_assert:
“4”,“24”,“42324”等,
如果参数是行
,我希望static_assert失败“4.0”,“3.00”,“2.99”,“3.01”,“ - 5”,“45n3mn”,“0”,“01”,“002”等,以及空条目
基本上,只有当宏中的参数是一个干净的整数字符串时,我才想让断言传递,我通过以下“算法”来做:
(1)如果stringified参数不仅仅是数字,则失败
(2)如果第一个char为'0',则失败
(3)如果为空,则失败
以下是我目前所拥有的,但由于错误“C2057:期望的常量表达式”而无法编译(我正在使用MSVS2013,但也希望构建g ++ 4.8兼容代码)。我不知道如何从static_assert中“调用”std :: string方法。
#define MyStaticAssert_isInt(num, message) \
static_assert(std::string(#num).find_first_not_of("0123456789") == std::string::npos, message) \
static_assert(std::string(#num).front() != '0', message) \
static_assert(!std::string(#num).empty(), message)
提前致谢!
答案 0 :(得分:4)
您可以尝试使用此用户定义的文字:
#include <cstddef>
#include <string>
constexpr bool operator ""_pure(char const * s, std::size_t len)
{
return len == 0 ||
('0' <= s[0] && s[0] <= '9' && operator ""_pure(s + 1, len - 1));
}
#define CHECK_INT(X) static_assert(X ## _pure, "Not pure")
int main()
{
CHECK_INT("123.0");
}
您当然可以将宏的字符串化部分。
答案 1 :(得分:2)
以下内容应该允许在编译时检查字符文字:
constexpr bool is_number_cont( const char* str )
{
return !*str || ( *str >= '0' && *str <= '9' && is_number_cont( str + 1 ) );
}
constexpr bool is_number( const char* str )
{
return *str >= '1' && *str <= '9' && is_number_cont( str + 1 );
}
int main()
{
static_assert( is_number( "123" ), "123 failed" );
static_assert( is_number( "0" ), "0 failed" );
static_assert( is_number( "" ), "empty string failed" );
static_assert( is_number( "1.23" ), "1.23 failed" );
static_assert( is_number( "abc" ), "abc failed" );
}
您可以在任何地方添加支票,包括在宏中。
如果您遇到C ++ 11之前的编译器,您可以使用手动扩展到有限的固定长度:
#define is_number(S) \
S[0]>='1' && S[0]<='9' && \
(!S[1] || (S[1]>='0' && S[1]<='9' && \
(!S[2] || (S[2]>='0' && S[2]<='9' && \
(!S[3] || (S[3]>='0' && S[3]<='9' && \
(!S[4] || (S[4]>='0' && S[4]<='9' && \
!S[5]))))))))
如果您需要检查更长的字符串,请展开它,显然该怎么做。