什么阻止在编译时评估constexpr?

Vik*_*ehr 5 c++ template-meta-programming constexpr c++11

考虑以下代码:

#include <unordered_set>
#include <type_traits>
#include <cstring>

constexpr auto cstring_hash(const char* istring) -> size_t {
    return (*istring) == '\0' ?
        size_t(0):
        (*istring) + cstring_hash(istring + 1);
}

constexpr auto cstring_length(const char* istring) -> size_t {
    return (*istring) == '\0' ?
        size_t(0):
        size_t(1) + cstring_length(istring + 1);
}

class PrehashedString {
public:
    constexpr PrehashedString(const char* istring) 
    : str_(istring)
    , hash_(cstring_hash(istring))
    , size_(cstring_length(istring)) {
    }
    constexpr auto& get_hash() const { return hash_; }
    auto operator==(const PrehashedString& iother) const {
        return 
            size_ == iother.size_ &&
            std::strcmp(str_, iother.str_) == 0;
    }
private:
    const char* str_;
    size_t hash_;
    size_t size_;
};

namespace std {
template <>
struct hash<PrehashedString> {
constexpr auto operator()(const PrehashedString& ihashed_string) const -> size_t {
    return ihashed_string.get_hash();
}
};
}
Run Code Online (Sandbox Code Playgroud)

为什么hash0(str0创建的地方)在运行时得到评估hash1(在哪里str1通过引用创建)在编译时得到评估?我在MSVCGCC 6.2/7.0中都尝试过它,看起来它们都失败了.它是否在标准中阻止在编译时对其进行评估?

auto func0() {
  const auto str0 = PrehashedString("my_string_0");
  const auto hash0 = str0.get_hash();

  const auto& str1 = PrehashedString("my_string_1");
  const auto hash1 = str1.get_hash();

  return hash0 + hash1;
}
Run Code Online (Sandbox Code Playgroud)

进一步扩展它,我如何强制它在编译时使用constexpr函数进行评估:

auto func1(std::unordered_set<PrehashedString>& iset) {
  return iset.count("my_key");
}
Run Code Online (Sandbox Code Playgroud)

注意: 我知道如何通过使构造函数只接受字符串文字(template <size_t N> PrehashedString(const char (&istring)[N]){...}),并利用字符串文字长度作为哈希函数的模板参数来实现这一点,我只是好奇它失败的原因.