您可能知道,C++ 11引入了constexpr关键字.
C++ 11引入了关键字constexpr,它允许用户保证函数或对象构造函数是编译时常量.[...]这允许编译器理解并验证[函数名称]是编译时常量.
我的问题是为什么对可以声明的函数的形式有严格的限制.我理解保证功能是纯粹的愿望,但考虑到这一点:
在函数上使用constexpr会对函数的作用施加一些限制.首先,该函数必须具有非void返回类型.其次,函数体不能声明变量或定义新类型.第三,正文可能只包含声明,空语句和单个return语句.必须存在参数值,以便在参数替换后,return语句中的表达式生成常量表达式.
这意味着这个纯函数是非法的:
constexpr int maybeInCppC1Y(int a, int b)
{
if (a>0)
return a+b;
else
return a-b;
//can be written as return (a>0) ? (a+b):(a-b); but that isnt the point
}
Run Code Online (Sandbox Code Playgroud)
你也不能定义局部变量... :(所以我想知道这是一个设计决定,还是编译器吮吸来证明功能a是纯粹的?
基本上我想在我的代码中能够做到这一点:
Engine.getById(WSID('some-id'));
Run Code Online (Sandbox Code Playgroud)
哪个应该改变
Engine.getById('1a61bc96');
Run Code Online (Sandbox Code Playgroud)
就在编译成asm之前.所以在编译时.
这是我的尝试
constexpr int WSID(const char* str) {
boost::crc_32_type result;
result.process_bytes(str,sizeof(str));
return result.checksum();
}
Run Code Online (Sandbox Code Playgroud)
但是在尝试使用MSVC 18(CTP 2013年11月)编译时我得到了这个
error C3249: illegal statement or sub-expression for 'constexpr' function
Run Code Online (Sandbox Code Playgroud)
WSID只要在编译期间完成,我怎样才能以这种方式或任何方式获得该函数?
试过这个:编译时间字符串哈希
warning C4592: 'crc32': 'constexpr' call evaluation failed; function will be called at run-time
Run Code Online (Sandbox Code Playgroud)
编辑:
我第一次在Jason Gregory的游戏引擎架构中听说过这种技术.我联系了那位有意回答我的作者:
我们所做的是通过一个自定义的小预处理器传递我们的源代码,该预处理器搜索表单的文本
SID('xxxxxx')并将单引号之间的任何内容转换为其哈希等效项作为十六进制文字(0xNNNNNNNN).[...]你可以想象通过宏和/或一些模板元编程也可以做到这一点,尽管如你所说让编译器为你做这种工作是很棘手的.这并非不可能,但编写自定义工具更容易,也更灵活.[...]
另请注意,我们为
SID('xxxx')文字选择单引号.这样做是为了让我们在代码编辑器中得到一些合理的语法突出显示,但是如果出现问题并且一些未预处理的代码通过编译器,它会引发语法错误,因为单引号通常是保留的单字符文字.另请注意,让您的小预处理工具将字符串缓存到某种类型的数据库中是至关重要的,这样可以在给定哈希码的情况下查找原始字符串.当您调试代码并检查
StringId变量时,调试器通常会向您显示相当难以理解的哈希代码.但是使用SID数据库,您可以编写一个插件,将这些哈希代码转换回其字符串等效项.这样,你会在你的观察窗口看到SID('foo'),而不是0x75AE3080[...].此外,游戏应该能够加载这个相同的数据库,以便它可以在屏幕上打印字符串而不是十六进制哈希码用于调试目的[...].
但是虽然预处理有一些主要优点,但这意味着我必须准备一些修改文件的输出系统(那些将存储在别处,然后我们需要告诉MSVC).因此,它可能会使编译任务复杂化.有没有办法用python预处理文件,例如没有头痛?但这不是问题,我仍然对使用编译时功能感兴趣(关于缓存我可以使用ID索引)