Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在实现std::hash时修改内部结构<;T>;_C++_C++11_Hash_Constants_Unordered Set - Fatal编程技术网

C++ 在实现std::hash时修改内部结构<;T>;

C++ 在实现std::hash时修改内部结构<;T>;,c++,c++11,hash,constants,unordered-set,C++,C++11,Hash,Constants,Unordered Set,我正在编写一个自定义的OrderedTree类,我想用作无序集的键 在对树进行哈希运算时,我想做几件事: 惰性地计算散列并根据需要缓存它(因为这可能是一个昂贵的操作) 也许平衡一下这棵树 这两个操作都不会更改对象的语义相等或哈希值,但会修改一些私有字段 不幸的是,在std::hash::operator()内尝试修改OrderedTree中的任何成员似乎违反了unordered\u set所期望的常量正确性 我可以将我的OrderedTree与无序集一起使用吗?如果是,怎么做 编辑: 根据评论中

我正在编写一个自定义的
OrderedTree
类,我想用作
无序集的键

在对树进行哈希运算时,我想做几件事:

  • 惰性地计算散列并根据需要缓存它(因为这可能是一个昂贵的操作)
  • 也许平衡一下这棵树
  • 这两个操作都不会更改对象的语义相等或哈希值,但会修改一些私有字段

    不幸的是,在
    std::hash::operator()
    内尝试修改
    OrderedTree
    中的任何成员似乎违反了
    unordered\u set
    所期望的常量正确性

    我可以将我的
    OrderedTree
    无序集一起使用吗?如果是,怎么做

    编辑:

    根据评论中的要求,最低限度的概念证明:

    #include <unordered_set>
    
    std::size_t hash_combine(std::size_t a, std::size_t b) {
      // TODO: Copy from boost source or something
      return 0;
    }
    
    struct Node {
      int value;
      Node *left, *right, *parent;
    
      std::size_t hash(std::size_t seed) const {
        if (left != nullptr)
          seed = left->hash(seed);
        std::hash<int> hasher;
        seed = hash_combine(seed, hasher(value));
        if (right != nullptr)
          seed = right->hash(seed);
        return seed;
      }
    };
    
    struct Tree {
    
      Tree(): hash_(0), root(nullptr) {}
    
      Node *root;
    
      std::size_t hash() const {
        if (hash_ == 0 && root != nullptr) {
          hash_ = root->hash(7);
        }
        return hash_;
      }
    
    private:
      std::size_t hash_;
    };
    
    namespace std {
      template<>
      struct hash<Tree> {
        std::size_t operator()(const Tree& t) const {
          return t.hash();
        }
      };
    }
    
    int main() {
      std::unordered_set<Tree> set;
    }
    

    可以保证,std容器在执行
    const
    或逻辑
    const
    操作时只调用
    const
    成员。如果那些
    const
    操作是多读卡器安全的,那么容器也是安全的;相反,如果不是,容器也不是


    散列值的不变性和相等性(或
    可以保证std容器在执行
    const
    或逻辑上
    const
    操作时只调用
    const
    成员。如果这些
    const
    操作是多读卡器安全的,那么容器也是安全的;反之,如果不是,那么容器也不是安全的


    哈希值和等式的不变性(或
    如何“似乎违反常量正确性”显化本身?这只是一些普遍的焦虑,或者你不知道如何实现它,或者你有编译器错误吗?听说过关键字“可变”吗?@JVApen我以前没有听说过。谢谢!这似乎正是我想要的。如果你用它来发布答案,我会接受的。@PeteBecker当我发布这个问题时,这一切都在我的脑海中,b但我会在一两分钟内尝试提出一个概念证明,“似乎违反了常量的正确性”是怎么回事显化本身?这只是一些普遍的焦虑,或者你不知道如何实现它,或者你有编译器错误吗?听说过关键字“可变”吗?@JVApen我以前没有听说过。谢谢!这似乎正是我想要的。如果你用它来发布答案,我会接受的。@PeteBecker当我发布这个问题时,这一切都在我的脑海中,b但我会尝试在一两分钟内提出一个概念证明当你说“一个使用强制转换来绕过…”时,你的意思是
    const\u cast
    对吗?一个带有
    mutable
    的程序仍然运行良好?我同意你对
    const
    的态度,我不确定我是否真的会使用
    mutable
    ,但我想学习更多关于危险的特性,所以如果我真的需要,我可以使用它们。@math
    const\u cast
    或等效的C型cast,是的。在声明的
    const
    上违反
    const
    (而不仅仅是
    const&
    到非
    const
    )UB.
    可变
    成员在这个意义上不会违反
    常量
    ,即使在
    常量
    方法中修改。当你说“使用强制转换绕过…”的常量方法时,你的意思是
    常量
    对吗?具有
    可变
    的程序仍然表现良好?我同意你对
    常量
    的态度,并且我不确定我是否真的会使用
    mutable
    ,但我想了解更多关于危险特性的信息,以便在我真的需要时可以使用它们。@math
    const\u cast
    或等效的C型cast,是的。在声明的
    const
    上违反
    const
    (不仅仅是
    常量&
    到非
    常量
    )是UB。
    可变
    成员在这个意义上不会违反
    常量
    ,即使在
    常量
    方法中修改。
    Sample.cc:31:13: error: cannot assign to non-static data member within const member function 'hash'
          hash_ = root->hash(7);
          ~~~~~ ^
    Sample.cc:29:15: note: member function 'Tree::hash' is declared const here
      std::size_t hash() const {
      ~~~~~~~~~~~~^~~~~~~~~~~~