基本上我想在我的代码中能够做到这一点:
Engine.getById(WSID('some-id'));
应该由什么来转换
Engine.getById('1a61bc96');
就在汇编之前被编译。所以在编译时。
这是我的尝试
constexpr int WSID(const char* str) {
boost::crc_32_type result;
result.process_bytes(str,sizeof(str));
return result.checksum();
}
但是我在尝试使用MSVC 18(CTP November 2013)编译时遇到了这个问题
error C3249: illegal statement or sub-expression for 'constexpr' function
我该如何在编译时获取WSID
函数,使用任何方法都可以,只要在编译时完成即可?
尝试过这个:编译时字符串哈希
warning C4592: 'crc32': 'constexpr' call evaluation failed; function will be called at run-time
编辑:
我第一次听说这种技术是在Jason Gregory的《游戏引擎架构》中。我联系了作者,他友善地回答了我以下内容:
我们所做的是把源代码通过一个自定义的小预处理器,搜索形如
SID('xxxxxx')
的文本,并将单引号之间的任何内容转换为其哈希等效项作为十六进制文字(0xNNNNNNNN
)。[...]你也可以通过宏和/或一些模板元编程来实现,虽然正如你所说,让编译器为你完成这种工作比较棘手。这不是不可能的,但编写一个定制工具更容易且更灵活。 [...]
还要注意,我们选择单引号作为
SID('xxxx')
字面量。这是为了在我们的代码编辑器中获得一些合理的语法高亮显示,如果某些未经过预处理的代码到达编译器,则会抛出语法错误,因为单引号通常保留给单个字符字面量。还要注意,有一个小预处理工具缓存字符串,以便根据哈希码查找原始字符串。当您调试代码并检查
StringId
变量时,调试器通常会显示相当难懂的哈希码。但是,使用SID数据库,您可以编写一个插件将这些哈希码转换回其字符串等效项。这样,您将在观察窗口中看到SID('foo'),而不是0x75AE3080
[...].此外,游戏应该能够加载同一个数据库,以便在屏幕上打印字符串而不是十六进制哈希代码进行调试[...]。
虽然预处理有一些主要优点,但意味着我必须准备某种修改文件的输出系统(这些文件将存储在其他地方,然后我们需要告诉MSVC)。因此,它可能会使编译任务变得复杂。是否有一种方法可以用Python预处理文件,而不会头疼?但这不是问题,我仍然对使用编译时函数感兴趣(对于缓存,我可以使用ID索引)。
std::string const&
是一个字面类型(因为它是一个引用),因此可以作为constexpr函数的函数参数类型。clang++和g++也接受它(在C++11模式下)。 - dyp