c++ - 如何测试 constexpr 是否被正确评估

标签 c++ c++11 constexpr

我已经使用 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

我得到了正确的结果

即使这样

将私有(private) hashID 更改为公共(public) hashID

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

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

但是如果我使用私有(private) 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

最佳答案

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

例子:

static_assert(_StringLength("meow") == 4, "The length should be 4!");

这还会检查您的函数是否正确计算结果。

关于c++ - 如何测试 constexpr 是否被正确评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28988426/

相关文章:

c++ - 如何查看VisualStudio对C/C++标准库的实现?

c++ - 我正在尝试用 C++ 创建一个日志记录框架,但信息没有传递给记录器的子组件,我做错了什么?

c++ - 在 cmake 中集成 bash 测试脚本

c++ - 一旦成为标准的一部分——boost 库会失去其 boost 命名空间并移至 std 吗?

c++ - 在转发引用上调用时自定义类型转换运算符不起作用(当对象按值传递时起作用)

c++ - 如何在另一个模板化结构中使用模板化结构 (C++)

适用于 Windows XP SP1 的 C++11

c++ - 模板类中的静态非模板方法

c++ - constexpr 变量必须由 const 表达式初始化

c++ - 什么时候应该在 C++11 中使用 constexpr 功能?