让std::map::operator[]变聪明

std::map::operator[]是一个设计得很磋却很好用的接口,看下面的例子:

 

#include <map>

#include <iostream>

 

using namespace std;

 

int main()

{

  map<int, int> iiMap;

  iiMap[1] = 2; ---------------------------(1)

  iiMap[2]; --------------------------------(2)

  cout << iiMap[1] << iiMap[2] << iiMap[3] << endl;

  return 0;

}

 

operator[]的语义是说:我先查一下这个key,如果没有就先插入一个pair(key, Value()),然后把value的引用返回。

 

当(2)这样用时,它也会插入一对值(2,0),实际上你可能不希望这么做,可能你只是想看看key=2的值是多少或者存不存在?是的,它没有意识到何时需要,一定需要插入新值。显然,当[]作左值时需要,作右值时只要查一下就够了。

 

以自己的一个hash_table类为例,实现就省了,它有2个不磋的接口:

 

template<typename Key, typename Value, ...>

class hash_table

{

public:

  Value* Get_Value(const Key& key);

  Value* Set_Value(const Key& key, const Value& value);

...

};

 

为了实现更好的operator[],这个接口被设计成:

 inline ValueWrapper operator[](const Key& key)
 {
  return ValueWrapper(key, Get_Value(key), this);
 }

 

ValueWrapper是一个托管类,它是Value的一个包装:

 class ValueWrapper
 {
  Key     key;
  Value*    pValue;
  hash_table_impl* mother;

 public:
  ValueWrapper(const Key& _key, Value* _pValue, hash_table_impl* _mother) :
  key(_key), pValue(_pValue), mother(_mother)
  {
  }

  ...

 };

 

它再重载operator=和operator Value,如下:

  ...

  operator Value()
  {
   if (pValue)
   {
    return *pValue;
   }
   else
   {
    return Value();
   }
  }

  ValueWrapper& operator=(const Value& value)
  {
   if (pValue)
   {
    *pValue = value;
   }
   else
   {
    mother->Set_Value(key, value);
   }
   return *this;
  }
 };

这样基本功能就完成了,它能感知=运算符,同时不失一般的在一些地方被隐式转化成Value。

 

如此还不够,像+= -= ++ --这些运算符也能代表着必须是左值,你如果一个一个重载,很麻烦,再写一个一般的包装类:

template<typename T>
class TypeWrapper
{
public:
 explicit TypeWrapper(T* pReff = NULL) : m_pReff(pReff)
 {
 }

 virtual ~TypeWrapper()
 {
 }

 ...

protected:
 virtual T& get_lvalue()
 {
  return *m_pReff;
 }

 virtual T get_rvalue()
 {
  if (m_pReff)
  {
   return *m_pReff;
  }
  else
  {
   return T();
  }
 }
};

 

提供2个虚接口,他们分别是取左值和取右值,然后把所有赋值运算符++,--和operator T都重载好(使用宏减少重复性代码),如此再由它继承出前面的ValueWrapper,这样更简单,这样一个聪明的operator[]完成,它能在需要的时候insert一个新值,而其它时间都是在查看。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值