【问题标题】:constexpr does not work/apply inside function callconstexpr 在函数调用中不起作用/适用
【发布时间】:2019-01-30 22:19:52
【问题描述】:

我已经实现了一个constexpr compile-time hash-function,如果调用它,它可以正常工作(即在编译时评估)

constexpr auto hash = CompileTimeHash( "aha" );

但我需要在实际代码中使用它作为函数的参数,如

foo( CompileTimeHash( "aha" ) ); // foo is NOT constexpr

由于特定原因,我不能使用长版本

constexpr auto hash = CompileTimeHash( "aha" );
foo( hash );

编译器 (VC++) 不会在短(第一种)情况下编译时散列。 有什么方法可以实现吗?

编辑:现在可以在此处找到涵盖 3 种情况的示例: https://godbolt.org/z/JGAyuE 只有 gcc 在所有 3 种情况下都能完成

【问题讨论】:

  • 您如何知道哈希函数是在运行时计算的?
  • @Someprogrammerdude "你怎么知道哈希函数是在运行时计算的?"您可以通过在 static_assert 中调用它来检查
  • 您使用的是哪个版本的 VC++?另外,我们可以得到一个minimal reproducible example 来测试其他编译器吗?
  • @Someprogrammerdude 你look at the disassembly
  • 等等,调试或发布版本中的断点?调试不相关;发布是不可信的。再说一遍,你怎么知道? nm 是一个强有力的例子。

标签: c++ c++17 constexpr compile-time compile-time-constant


【解决方案1】:

好吧,as-if-rule 总是允许在运行时进行评估。然而,这样做可能很疯狂(而且极其复杂)。

强制编译器在编译时执行此操作的最佳方法,通过模板参数传递它:

一些设置:

template <auto x>
using make_integral_constant = std::integral_constant<decltype(x), x>;

template <auto x>
inline constexpr auto want_static = make_integral_constant<x>::value;

并像这样使用它:

foo( want_static<CompileTimeHash( "aha" )> );

works even without optimization,因为除非您使用解释器,否则在运行时执行此操作太复杂,无法无缘无故地执行。


分配给constexpr-变量也应该有效。但实际上在编译时不评估更容易,所以without optimization that happens anyway

foo( []{ constexpr auto r = CompileTimeHash( "aha" ); return r; }() );

更新:在 C++ 20 中,新关键字 consteval 可用于定义立即函数,该函数将始终在编译时进行评估。 constinit 可用于强制使用 constexpr 规则进行初始化,而无需设置为 constexpr

consteval auto immediate(auto x) { return x; }

【讨论】:

    【解决方案2】:

    如果我理解正确,您的CompileTimeHash() 会返回int

    那么

    foo( sizeof(char[CompileTimeHash( "aha" )]) );
    

    ?

    如果CompileTimeHash() 显然只返回正数。

    如果CompileTimeHash() 返回非负数(正数或零),则可以解决零问题(不能作为 C 样式数组的大小)加(内)和减(外)1

    我是说

    foo( sizeof(char[CompileTimeHash( "aha" )+1])-1u );
    

    【讨论】:

    • @old123987 - 嗯……不;如果CompileTimeHash() 返回负数或零,这是行不通的;但有正数...
    • 即使它是 unsigned int 而不是 int - 这是一个复杂的解决方案。巴洛克式的,令人困惑的,可能会被未来的维护者撤销或以其他方式滥用。 -1.
    • 即使它是一个无符号整数,我的解决方案对于零情况也是有问题的;我不同意您的以下观点(令人费解的、巴洛克式的、令人困惑的……),但感谢您对投票的解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 2018-07-10
    • 1970-01-01
    • 2015-08-19
    • 2012-10-29
    • 1970-01-01
    相关资源
    最近更新 更多