免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 没本

C++字符串常量编译时转CRC32数值常量,有办法实现吗?(答案已经公开) [复制链接]

论坛徽章:
0
发表于 2012-02-05 18:52 |显示全部楼层
回复 8# OwnWaterloo


    如果是C++03,boost::mpl::string有一种比较丑陋的实现,但要写成
boost::mpl::string<'hello'>
boost::mpl::string<'This',' is ','a st','ring'>
    至于前面的crc32快查表,倒是可以不用变长参数模板,C++03就可以实现,方法是用预处理展开,或者直接用BOOST提供的BOOST_PP_ENUM。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 2012-02-05 18:53 |显示全部楼层
gtkmm 发表于 2012-02-05 18:32
1. "hello world"这样的东西, 是编译期常量, 应该叫“整形数组”, 而不是字符串(当然可以转化成字符串)。
    整形数组包含了完整类型信息, 比如长度。

2. crc32比较简单, 可以inline。

剩下的就很简单了。 不解释, 你明白的。


不明白……  能在c++03中实现么?


1. 非类型模板参数是不支持数组的,只支持指针。
而通过指针获取元素 ptr[idx] 是运行时求值, 即使ptr是编译时常量。

2. inline与编译时值不同。

inline int factorial(int x) { ... };
int f(void) { int y = factorial(3); // 也许这里产生的代码里会直接使用6,但它不是编译时值

比如,它不能这样 enum { Y = factorial(3) };
constexpr(c++11)才可以。

论坛徽章:
0
发表于 2012-02-05 18:55 |显示全部楼层
回复 9# OwnWaterloo


    constexpr做常量表达式函数时,限制颇多,目前不借助模板还做不到吧。

论坛徽章:
0
发表于 2012-02-05 19:09 |显示全部楼层
OwnWaterloo 发表于 2012-02-05 18:53
不明白……  能在c++03中实现么?


这个区别在于, inline需要打开gcc 2级优化, 而enum需要不管是否有优化的情况下都有用。
所以enum失败了。

论坛徽章:
0
发表于 2012-02-05 19:19 |显示全部楼层
回复 14# gtkmm


    如果inline要真能实现编译时计算的话,你不妨贴可用的代码来让大家学习一下。

论坛徽章:
0
发表于 2012-02-05 19:54 |显示全部楼层
本帖最后由 gtkmm 于 2012-02-05 19:56 编辑

crc32太长, 我实现个简单点的, 就是按位求和。

inline int  str_sum( const char (&str)[1]) {
  return str[0];
}

template <int N>  int  str_sum( const char (&str)[N]) {
  return str[N-1] + str_sum(((const char (&)[N-1])(str)));
}

int main(int argc, char *argv[]) {
  int id = str_sum("hello world");
  return 0;
}

用gcc 2级优化编译, 在2进制文件里,找不到hello world这样的字。
看汇编代码, 发现id被直接赋值的。

(模板函数, 也是inline的。)

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 2012-02-05 20:00 |显示全部楼层
回复 16# gtkmm

要 enum { x = str_sum("hello world") }; 才是编译时常量啊哥哥……
enum不是失败不失败的问题,而是题目的要求就是这个啊……

论坛徽章:
0
发表于 2012-02-05 20:19 |显示全部楼层
回复 16# gtkmm
这是-O2后的结果,被编译器优化掉了吧,不加-O2是能在执行文件中找到"hello world"字符串的。

  1. $ g++ -O2 -S cnt.cpp
  2. $ cat cnt.s
  3.         .file   "cnt.cpp"
  4.         .section        .text.startup,"ax",@progbits
  5.         .p2align 4,,15
  6.         .globl  main
  7.         .type   main, @function
  8. main:
  9. .LFB2:
  10.         .cfi_startproc
  11.         xorl    %eax, %eax
  12.         ret
  13.         .cfi_endproc
  14. .LFE2:
  15.         .size   main, .-main
  16.         .ident  "GCC: (Gentoo 4.6.2 p1.0, pie-0.4.5) 4.6.2"
  17.         .section        .note.GNU-stack,"",@progbits
  18. $
复制代码

论坛徽章:
0
发表于 2012-02-05 20:21 |显示全部楼层
要不你换个复杂点的算法,求和太容易被编译器优化了。

论坛徽章:
0
发表于 2012-02-05 20:32 |显示全部楼层
本帖最后由 没本 于 2012-02-05 20:33 编辑

还有就是OwnWaterloo在17楼提到的,这个似乎只能放到函数体里面给变量运行时赋值,无法对常量进行初始化。打开-std=C++0x也不行。也无法给全局变量赋值。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP