如何测试constexpr是否正确评估

问题描述 投票:8回答:6

我已经使用constexpr在编译时计算哈希码。代码正确编译,运行正确。但是我不知道,哈希值是编译时还是运行时。如果我在运行时跟踪代码,则不会执行constexpr函数。但是,即使对于运行时值也不会跟踪这些值(为运行时生成的字符串计算哈希-相同的方法)。我试图研究反汇编,但我不太了解]

出于调试目的,我的哈希码仅为字符串长度,使用此方法:

constexpr inline size_t StringLengthCExpr(const char * const str) noexcept
{
    return (*str == 0) ? 0 : StringLengthCExpr(str + 1) + 1;
};

我有这样创建的ID类

class StringID
{
    public:
       constexpr StringID(const char * key);
    private:
       const unsigned int hashID;
}

constexpr inline StringID::StringID(const char * key)
        : hashID(StringLengthCExpr(key))
{

}

如果我在程序main方法中执行此操作

StringID id("hello world"); 

我得到了这个反汇编的代码(部分内容-内联方法和main中的其他内容有很多)

;;;     StringID id("hello world"); 

        lea       eax, DWORD PTR [-76+ebp]                     
        lea       edx, DWORD PTR [id.14876.0]                   
        mov       edi, eax                                     
        mov       esi, edx                                     
        mov       ecx, 4                                       
        mov       eax, ecx                                      
        shr       ecx, 2                                        
        rep   movsd                                            
        mov       ecx, eax                                      
        and       ecx, 3                                       
        rep   movsb                                            

// another code

我如何由此得知,“哈希值”是一个编译时间。我没有看到像11这样的常量移到寄存器中。我对ASM不太满意,所以也许它是正确的,但是我不确定要检查什么或如何确定“哈希代码”值是编译时的,而不是在运行时根据此代码计算的。

((我正在使用Visual Studio 2013 + Intel C ++ 15编译器-VS编译器不支持constexpr)

编辑:

如果我更改代码并执行此操作

    const int ix = StringLengthCExpr("hello world");

    mov       DWORD PTR [-24+ebp], 11                       ;55.15

我得到正确的结果

甚至与此

将私有hashID更改为public

 StringID id("hello world"); 
  // mov       DWORD PTR [-24+ebp], 11                       ;55.15

 printf("%i", id.hashID);
  // some other ASM code

但是,如果我使用私有hashID并添加Getter,则>]

  inline uint32 GetHashID() const { return this->hashID; };

到ID班,然后我得到了

  StringID id("hello world"); 
  //see original "wrong" ASM code

  printf("%i", id.GetHashID());
  // some other ASM code

我已经使用constexpr在编译时计算哈希码。代码正确编译,运行正确。但是我不知道,哈希值是编译时还是运行时。如果我在运行时跟踪代码,则... ...>

c++ c++11 constexpr
6个回答
22
投票

最方便的方法是在constexpr语句中使用static_assert。如果在编译时未对其进行评估,则该代码将无法编译,并且static_assert表达式将在运行时不给您任何开销(并且不会产生像模板解决方案那样的不必要的生成代码)。

示例:


5
投票

如果要确保在编译时评估constexpr函数,请在需要编译时评估的情况下使用其结果:


1
投票

有几种方法可以强制进行编译时评估。但是这些功能不像使用constexpr时所期望的那样灵活且易于设置。而且,它们不能帮助您确定是否实际使用了编译时常量。


1
投票

以下技巧可以帮助检查constexpr函数是否仅在编译时进行了评估:


1
投票

简单地将其放在constexpr变量中。


0
投票

将来(c ++ 20),您可以使用consteval说明符来声明一个函数,该函数必须在编译时进行评估,因此需要constant expression上下文。

© www.soinside.com 2019 - 2024. All rights reserved.