我正在寻找一种创建string_id的方法,该字符串将在调试时为字符串,而在发布时为哈希,而无需用户做过多的工作(即,不提供id和字符串)。我已经按照互联网的建议实施了fnv1a,这就是我得到的:
#ifdef HASH_STRING_IDS
#include <cstdint>
#define StringId std::uint32_t
constexpr StringId fnv1a(char const* s, std::size_t count)
{
return ((count ? fnv1a(s, count - 1) : 2166136261u) ^ s[count]) * 16777619u;
}
constexpr StringId operator"" _id(char const* s, std::size_t count)
{
return fnv1a(s, count);
}
#else // HASH_STRING_IDS
#include <string>
#define StringId std::string
StringId operator"" _id(char const* s, std::size_t count)
{
return{ s, count };
}
#endif // HASH_STRING_IDS
问题是gcc很好,它将在编译时评估id,但是clang和MSVC都不会(即使在最高级别的优化下,哈希也要在执行时计算);的示例:
#ifdef HASH_STRING_IDS
std::uint32_t doStuff(StringId id)
{
return id * 7;
}
#else // HASH_STRING_IDS
std::uint32_t doStuff(StringId id)
{
return id.size() * 7;
}
#endif // HASH_STRING_IDS
int main()
{
return doStuff("test"_id);
}
有什么原因吗?
我遇到的另一个问题是我无法检测到碰撞,并且希望如此。有什么聪明的方法可以做到这一点吗?
感谢您的回复:)