Thursday, August 18, 2011

map::iterator: избавляемся от ->first и ->second

Решил тут в процессе изучения С++ старый свой код порефакторить. Попался такой вот кусочек:
typedef unordered_map<int,double> ColumnMap;
typedef ColumnMap::const_iterator ColumnMapIter;
...
for(ColumnMapIter it = row->begin(); it != row->end(); ++it) {
    ColumnMap *tmp = other -> rlist[it -> first];
    ColumnMapIter it_col = tmp -> find(col);
    if (it_col != tmp->end()) {
        val += (it -> second ) * (it_col -> second);
    }
}
Согласитесь, что в этих first и second чёрт ногу сломит. Однако в плюсах имеется такая редкоиспользуемая фича, как указатели на члены класса. Почитать про них можно, например, здесь: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=142
С их-то помощью и можно заменить first и second на что-нибудь более понятное.

Смотрите:
typedef unordered_map<int,double> ColumnMap;
typedef ColumnMap::const_iterator ColumnMapIter;
...
typedef ColumnMap::value_type ColumnMapPair;
const ColumnMapPair::first_type ColumnMapPair::* column = &ColumnMapPair::first;
ColumnMapPair::second_type ColumnMapPair::* value = &ColumnMapPair::second;
...
for(ColumnMapIter it = row->begin(); it != row->end(); ++it) {
    ColumnMap *tmp = other -> rlist[*it.*column];
    ColumnMapIter it_col = tmp -> find(col);
    if (it_col != tmp->end()) {
        val += (*it.*value) * (*it_col.*value);
    }
}

No comments:

Post a Comment