【问题标题】:Operator overloading for C++ mapsC++ 映射的运算符重载
【发布时间】:2010-09-13 14:25:14
【问题描述】:

我需要帮助理解一些 C++ 运算符重载语句。类是这样声明的:

template <class key_t, class ipdc_t>
class ipdc_map_template_t : public ipdc_lockable_t
{
    ...
    typedef map<key_t,
            ipdc_t*,
            less<key_t>> map_t;
    ...

类的创建者为内部映射结构创建了一个迭代器:

struct iterator : public map_t::iterator
{
    iterator() {}
    iterator(const map_t::iterator & it)
        : map_t::iterator(it) {}
    iterator(const iterator & it)
        : map_t::iterator(
            *static_cast<const map_t::iterator *>(&it)) {}
    operator key_t() {return ((this->operator*()).first);}           // I don't understand this.
    operator ipdc_t*() const {return ((this->operator*()).second);}  // or this.

};

而 begin() 和 end() 返回地图的 begin() 和 end():

iterator begin() {IT_ASSERT(is_owner()); return map.begin();}
iterator end() {return map.end();}

我的问题是,如果我有一个迭代器,我如何使用这些重载来获取键和值?

ipdc_map_template_t::iterator iter;
    for( iter = my_instance.begin();
             iter != my_instance.end();
         ++iter )
    {
        key_t my_key = ??????;
        ipdc_t *my_value = ??????;

    }

【问题讨论】:

  • 下面提供的解决方案已经足够好(但可能存在值的指针问题),所以 In 不会详细说明......但无论如何:使用隐式强制转换作为语法糖是不好的危险的设计,恕我直言...

标签: c++ templates


【解决方案1】:

这些是类型转换运算符,因此您可以这样做:

{
    key_t   key = iter;
    ipdc_t *val = iter;
}

或者,由于ipdc_map_template::iteratorstd::map::iterator 的子类,您仍然可以使用原始访问器(我觉得它更易读):

{
    key_t   key = (*iter).first;
    ipdc_t *val = (*iter).second;

    // or, equivalently
    key_t   key = iter->first;
    ipdc_t *val = iter->second;

}

【讨论】:

  • iter->first 看起来比 (*iter).first IMO 好,因为它不需要括号。
  • 我喜欢 Greg 的版本,但是,无论如何,使用 std::map 标准接口而不是通过滥用强制转换运算符重载来破解自己的方式是对的......
【解决方案2】:

operator key_t() 和 operator ipdc_t*() 都是强制转换定义。因此,给定类中定义的迭代器,您应该能够简单地分配变量:

ipdc_map_template_t::iterator iter;
    for( iter = my_instance.begin();
         iter != my_instance.end();
         ++iter )
    {
            key_t my_key = iter;
            ipdc_t my_value = iter;
    }

【讨论】:

    【解决方案3】:

    类的创建者已经覆盖了强制转换操作符。 因此,只需将 iter 分配给正确类型的对象,它就应该通过方法自动将自身转换为正确的值。

    注意:值类型被存储为指针。因此,当您提取值时,您需要指定指向您在映射接口中指定的值类型的指针。

     typedef ipdc_map_template_t<int,std::string>   MyMap;
     MyMap    mymap;
    
     for(MyMap::iterator iter = mymap.begin();
                         iter != mymap.end();
                         ++iter )
        {
                int          my_key   = iter;
                std::string* my_value = iter;
    
        }
    

    不确定我是否同意此处采取的方向。 这是否使代码更具可读性?我会坚持使用老式的地图迭代器听起来更有用。这个容器是在您需要的某个专门的库中定义的,还是查看 boost 指针容器是否有益?

    【讨论】:

    • 您能验证您的代码吗?我想你是对的,但有一件事是:地图正在操纵值的指针,而不是值本身。所以我猜用户将不得不做“std::string * my_value = iter;”......或者我应该去睡觉...... :-p
    • 只是咳咳。但是当你只得到类的部分定义时,很难验证代码。
    猜你喜欢
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 2017-06-14
    相关资源
    最近更新 更多