【问题标题】:Custom Key for std::map<> [duplicate]std::map<> 的自定义键 [重复]
【发布时间】:2023-03-21 23:14:02
【问题描述】:

我正在尝试使用以下struct 作为std::map 的自定义键:

struct ActionId {
        // ENCAPSULATED MEMBERS
    private:
        size_t _id;
        static size_t _root;
        static size_t incrementedRoot() {
            return (_root += 1);
        }

        // INTERFACE
    public:
        ActionId() :
            _id(incrementedRoot()) { }
        ActionId(const ActionId& that) :
            _id(that._id) { }
        ActionId& operator=(const ActionId& that) {
            this->_id = that._id;
            return *this;
        }
        bool operator==(const ActionId& that) const {
            return this->_id == that._id;
        }
        bool operator!=(const ActionId& that) const {
            return this->_id != that._id;
        }
        bool operator<(const ActionId& that) const {
            return this->_id < that._id;
        } 
};

以下字典是单独的InputManager 类的成员:

std::map<ActionId, std::set<sf::Keyboard::Key>> _keyBindings;

在此成员函数中访问:

std::set<sf::Keyboard::Key> InputManager::keysBoundTo(ActionId action) const {
    return _keyBindings[action];
}

不幸的是,该函数抛出此编译器错误:

错误 C2678: 二进制 '[' : 未找到采用 'const std::map&lt;Game2D::ActionId,std::set&lt;sf::Keyboard::Key,std::less&lt;_Kty&gt;,std::allocator&lt;_Kty&gt;&gt;,std::less&lt;Game2D::ActionId&gt;,std::allocator&lt;std::pair&lt;const Game2D::ActionId,_Ty&gt;&gt;&gt;' 类型的左侧操作数的运算符(或没有可接受的转换)

根据this articleActionIdoperator&lt;() 成员具有const 资格应该足以使其成为自定义地图键,而this article 表示我所需要的只是使ActionId 可复制和可分配的。很明显,我的结构满足这两个条件,那为什么InputManager::keysBoundTo() 不能编译呢?

【问题讨论】:

  • 你看错了地方。 map::operator[] 不是 const

标签: c++ struct key stdmap


【解决方案1】:

索引运算符(“[]”)是 std::map 的非常量成员函数。鉴于您已经明确指出 keysBoundTo 是一个 const 成员。

keysBoundTo重写为

std::set<sf::Keyboard::Key> InputManager::keysBoundTo(ActionId action) const
{
    auto it = keyBindigs_.find(action);
    if ( it == keyBindings_.end() )
        return std::set<sf::Keyboard::Key>();
    else
        return it->second;
}

请注意,我将您的成员变量重命名为尾部有下划线。不要使用带有前导下划线的标识符。

【讨论】:

  • 哇,没想到会这样。那么你是说,在这种情况下,operator[] 返回一个可修改的std::set&lt;&gt;&amp; 对象,并且没有从该对象到const std::set&lt;&gt;&amp; 的转换?我觉得这相当令人惊讶。不过,您的代码编译得很好,谢谢 :) 另外,您为什么不推荐前导下划线?
  • 不,这与可修改或不可修改的值(本例中的集合)无关。正如我在回答中所说,std::map 的 operator[] 是一个 non-const 成员。它可以修改映射(如果没有找到,则插入与输入对应的键)。
  • 带前导下划线的标识符由实现(即编译器编写者)保留。
  • @HappyGreenKidNaps 这是一个简化。 _Ugly__ugly 在任何地方都保留。 _ugly 仅保留在全局命名空间中
猜你喜欢
  • 1970-01-01
  • 2017-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
相关资源
最近更新 更多