我有一个API,它需要尽可能简单。同时,某些函数的字符串是“众所周知的”,并且字符串文字总是如此,因此可以在编译时将其转换为CRC32值,例如:
function(crc32("text"), ...);
校验和发生在使用constexpr的编译时。
我想简化此API,以便与我一起工作的人不必知道这些毫无意义的细节。我想使编译时校验和发生在函数内部,例如:
function("text", ...);
在内联函数中执行校验和不起作用,因为函数参数不再是constexpr。以下代码将无法编译:
inline void function (const char* text, ...) {
constexpr uint32_t hash = crc32(text); // does not work
}
这是针对仿真环境的,因此至关重要的是,校验和必须在编译时进行。有几个这样工作的功能,它们都将从简化API中受益。
我必须隐藏哪些选项才能记住使用crc32的调用这一事实?
似乎没有其他选择,只能在这种情况下使用宏:
#define FUNCTION(text, ...) nspc::function(crc32(text), __VA_ARGS__)
请注意,即使在function(crc32("text"), ...)
的情况下,crc32("text")
调用的上下文也不是constexpr
,因此不能保证它在编译时会发生。您需要consteval
这样的保证。
类似于宏解决方案,您可以将字符串文字包装在存储字符串及其校验和的帮助程序“ checksummer”类中,并接受它作为参数。这样,校验和发生在调用函数[[before之前,好的编译器将在编译时针对编译时已知的字符串进行此操作。
例如:consteval
我们可以在[G0]和[clang]中将#include <string_view> constexpr uint32_t checksum(std::string_view sv) noexcept { uint32_t sum = 0; for (unsigned char c : sv) sum += c; return sum; } struct StrWithSum { const char* str; const uint32_t sum; constexpr StrWithSum(const char* p) : str(p), sum(checksum(p)) {} }; uint32_t do_something(StrWithSum str) { return str.sum + 2; } int main() { return do_something("ABC"); static_assert(StrWithSum("ABC").sum == 198, "sum"); }
函数编译为see操作:
do_something
以及整个程序到
+ 2
(不幸的是,VC ++中不是这种情况。