【问题标题】:Constantly inlining a function with a consteval call使用 consteval 调用不断内联函数
【发布时间】:2021-12-10 06:19:15
【问题描述】:

我有一个 consteval crc32 函数,它在编译时工作得很好。我希望这个函数在另一个常量内联函数中使用。

下面是一个代码示例,便于理解:

unsigned int consteval strsum(const std::string str) {
    auto n = 0;

    for (int i = 0; i < str.size(); i++) n += str.at(i);

    return n;
}

void _printHash(const unsigned int hash) {
    printf("%d", hash);
}

__forceinline void printHash(const std::string str) {
    _printHash(strsum(str));
}

int main(int argc, char* argv[]) {
    printHash("abc");
}

我希望这段代码编译为:

int main(int argc, char* argv[]) {
    _printHash(/* hash constant */);
}

相反,我收到 C7595 错误:对 consteval 函数的调用不是常量表达式。

有没有办法在 MSVC 上实现想要的行为?

【问题讨论】:

  • 你试过__force_inline关键字吗?
  • @Mechap 刚刚试过。没有改变任何东西。
  • 编译这段代码时你使用了哪些编译器选项?
  • @Mechap 默认值:/JMC /permissive- /ifcOutput "Debug\" /GS /analyze- /W3 /Zc:wchar_t /ZI /Gm- /Od /sdl /Fd"Debug\vc142.pdb" /Zc:inline /fp:precise /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /std:c++20 /FC /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /Fp"Debug\TestConsole.pch" /diagnostics:column
  • 你的例子不是minimal reproducible example。如果不出意外,crc_table 是一个未声明的标识符。显示任何人都可以复制、粘贴到他们的编译器中并重现问题的代码。

标签: c++ visual-c++ constants constexpr consteval


【解决方案1】:

首先,你不能有一个带有 std::string 参数的 consteval 函数,因为它不是文字类型。幸运的是std::string_view 在这个应用程序中无限好,你可以拥有

consteval unsigned int strsum(const std::string_view str) {
    auto n = 0;
    for (auto s : str) n += s;
    return n;
}

遗憾的是,非consteval 函数的参数永远不是常量表达式,consteval 函数不能调用常规函数。所以即使你可以拥有strsum,你也不能调用你想要的方式。

您可以调用_printHash(strsum("abc")) 而不是printHash("abc"),但是如果您不能接受这种语法,那么恐怕您没有太多选择,除了接受生成的代码将循环一个常量字符串。

非 MSVC 的编译器将 do the right thing 不需要任何 constexprconsteval(或 inline),因此整个编译器将完全按照需要编译为等同于 printf("%d", 294) 的东西。但是 MSVC 就是不擅长这种优化。

【讨论】:

  • 你错了,std::string 实际上是 c++/20 的 constexpr。
  • 类型不能是constexpr。函数和变量可能是constexpr。为了使变量成为constexpr,它必须是文字类型。如果一个类型是字面量的,它可能可以创建一个constexpr vriable 或返回此类型的函数,但不能保证。我在标准中没有看到std::string是文字类型的要求,你能指出来吗?
  • 显然,即使它是字面的,MSVC 似乎是唯一实现它的编译器。
猜你喜欢
  • 1970-01-01
  • 2020-12-03
  • 1970-01-01
  • 2020-12-01
  • 2010-11-06
  • 1970-01-01
  • 2021-09-15
  • 2022-01-06
  • 1970-01-01
相关资源
最近更新 更多