Карта класса шаблона построена на stl :: vector of structs - ищет недопустимый ключ (stl :: string) и выдает исключение

0

Как и в заголовке, я пытаюсь написать карту классов шаблонов, которая строится на векторе structs, где я держу ключ, который является строкой и значением шаблона TYPE. Существует короткая основная программа, которая представляет использование моего класса:

int main()
{
  map<int> iv;

  iv["john"] = 23;

  int ia = iv["john"]++;
  int ib = iv["john"];

  cout << ia << " " << ib << endl; // prints 23 24
  try{
  int ic = iv["jack"];  // should throw an exception
  }catch(map<int>::Uninitialized&)
  {
    cout << "Uninitialized map element!" << endl;
  };
}

И есть класс, который мне удалось написать:

class map
{
private:
  struct FIELD
  {
    string key;
    TYPE value;
  };
  vector<FIELD> data;
public:
  TYPE& operator[] (const string index)
  {
    typename vector<FIELD>::iterator idx;
    for(idx = data.begin(); idx != data.end(); ++idx)
    {
      if(idx->key == index)     return idx->value;
    }
    if(idx == data.end())
    {
      FIELD toAdd;
      toAdd.key = index;
      data.push_back(toAdd);
    }
    for(idx = data.begin(); idx != data.end(); ++idx)
    {
      if(idx->key == index) return idx->value;
    }
    return idx->value;
  }
};

Он работает только для операций присваивания, таких как "iv [" john "] = 23; но когда я пытаюсь читать элементы, которые не инициализируются, оператор [] создает новый элемент, содержащий только ключ, и это неправильно. Я знаю, что нет такой вещи, как проверка того, является ли значение неинициализированным. Проблема в том, что оператор записи и чтения операции [], и я не совсем понимаю, как сделать исключение в этой ситуации. Я посмотрел по всему Интернету и обнаружил, что могу создать два оператора индексирования: один для чтения и один для записи - вот так:

TYPE& operator[] (const string index)
TYPE operator[] (const stirng index) const;

и компилятор будет знать, когда использовать. Но я думаю, это не решит проблему вообще.

  • 0
    В std::map они сделали это там, где operator[] всегда создает новый элемент автоматически с созданным по умолчанию T , и at это тот, который вызовет исключение, если его там нет.
  • 0
    Да, я знаю это, но как реализовать функцию at () в stl :: vector, где индексами являются stl :: string?
Показать ещё 3 комментария
Теги:
exception
vector
operator-keyword
map

1 ответ

1

Не пытайтесь повторно реализовать std::map, создайте вместо него псевдоним:

template<class Type>
using map = std::map<std::string, Type>;

Не забудьте импортировать using namespace std; , так как считается плохой практикой, и в этом случае у вас будет столкновение имен.

И да, std::map::operator[] всегда создавал элемент внутри карты. Вы можете использовать std::map::at чтобы заставить его std::out_of_range исключение std::out_of_range если элемент там отсутствует, или проверить с помощью map.find(key) == map.end().

Ваш главный станет:

int main() {
    map<int> iv;
    iv["john"] = 23;

    int ia = iv["john"]++;
    int ib = iv["john"];

    std::cout << ia << " " << ib << std::endl; // prints 23 24
    try {
        int ic = iv.at("jack");
        //         ^^^^      ^
    } catch(const std::out_of_range&) {
    //      ^^^^^^^^^^^^^^^^^^^^^^^^
        std::cout << "Uninitialized map element!" << std::endl;
    };
}
  • 0
    Что ж, такой подход был бы лучше, но мне не разрешено менять основную программу, и он должен создавать и имитировать поведение std :: map в разных контейнерах std. У меня возникла идея, что я мог бы создать два оператора индексирования, один для чтения и один для записи, затем один для записи будет работать так же, как сейчас, и что один для чтения будет проверять, существует ли индекс (строка), и если нет - выбрасывание и исключение. Для этого я также обнаружил, что в этом случае я должен создать вспомогательный класс, чтобы различать чтение и запись. Но я не совсем знаю, как реализовать это на моем примере

Ещё вопросы

Сообщество Overcoder
Наверх
Меню