【问题标题】:constexpr user-defined literal: Is it allowed?constexpr 用户定义文字:是否允许?
【发布时间】:2017-08-07 02:53:17
【问题描述】:

我正在尝试在编译时使用用户定义的文字对我的字符串进行哈希处理

constexpr unsigned int const_hash(char const *input) {
    return *input ?
        static_cast<unsigned int>(*input) + 33 * const_hash(input + 1) :
        5381;
}

constexpr unsigned int operator ""_hash (const char *input, size_t) {
    return const_hash(input);
}

int main(void) {
    printf("%i\n", "test"_hash);
    return 0;
}

它适用于 GCC

mov esi, 2090770981
mov edi, OFFSET FLAT:.LC0
xor eax, eax
call printf

但不在 MSVC 中

push     OFFSET ??_C@_04CEJDCDCH@test?$AA@+1
call     ?const_hash@@YAIPBD@Z
mov      ecx, eax
add      eax, 116   ; 00000074H
shl      ecx, 5
add      eax, ecx
push     eax
push     OFFSET ??_C@_03PELOGHMK@?$CFi?6?$AA@
call     _printf
add      esp, 12              ; 0000000cH

所以我猜 constexpr 用户定义的文字是一个 UB/编译器实现?是否在 FDIS 中指定?

(我知道递归 constexpr 函数是不允许的,但我以它为例)

编辑:

这是一个 FNV-1 非递归的:http://godbolt.org/g/KF9BaE

这里又是一个 DJB2 非递归的:http://godbolt.org/g/7eJmpp

我可以通过安装模板来强制执行恒定的哈希行为: http://godbolt.org/g/fsuFS9

但是我将不允许预先评估字符串文字运算符的哈希,因为参数中的字符串文字已经衰减为指针

【问题讨论】:

  • "我知道递归 constexpr 函数是不允许的,但我以它为例" 你有没有想过这可能是它不起作用的原因,而不是您正在使用 UDL 的事实?将 constexpr 函数不能做的事情用作测试似乎是有问题的,UDL 与否。
  • 不,我尝试了各种 constexpr C++ 哈希函数,包括 crc32、fnv1、djb2、递归和非递归,它们都具有相似的行为。
  • 我这里使用的 constexpr 哈希函数是 djb2 的变种。
  • 然后提供一个非递归的例子。
  • question 中包含相关信息,而不是下面的 cmets。随意编辑您的问题并将这些内容添加到其中。

标签: c++ templates template-meta-programming


【解决方案1】:

您的上下文不需要 constexpr,因此可以在运行时完成

printf("%i\n", "test"_hash);

你应该改成

constexpr auto test_hash = "test"_hash;
printf("%i\n", test_hash);

你观察到的是编译器的优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-27
    • 2017-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    相关资源
    最近更新 更多