Обнаружение плохого элемента, вставленного в std :: set - PullRequest
1 голос
/ 23 сентября 2011

Скажем, у меня есть собственный тип в моем наборе, и набор / упорядочение имеет смысл, только если все элементы имеют одно и то же значение в некотором свойстве ... если вставлен элемент с другим значением, модель облажается, и яхочу защитить это.

Я подумал, что, возможно, функция сравнения может быть местом, где мы могли бы проверить это (как утверждение или исключение), чтобы либо отметить проблему и / или предотвратить вставку элемента.Например, для TypeName оператор <() всегда возвращает false, если важный атрибут не равен. </p>

Это разумно?

Ответы [ 4 ]

6 голосов
/ 23 сентября 2011

Я полагаю, что при помещении его в компаратор могут возникнуть проблемы, поскольку у вас нет никаких гарантий, когда он будет вызван. Возможно, какая-то мифическая реализация хранит элементы в списке, когда количество элементов невелико, и не вызывает компаратор до тех пор, пока позже?

Вероятно, самым простым подходом было бы обернуть std::set в защитный внешний класс, который выполнил эти утверждения.

class MySet {
  private:
     std::set<myFunkyType> myType;

  public:
     void insert(myFunkyType type) {
        assert(!type.isFunky(), "funk violation");
        // and so on
     }

     // all other members other than insertion or mutation just delegate to the
     // underlying set

}

0 голосов
/ 23 сентября 2011

Когда в вашем операторе <вы обнаруживаете, что не можете установить строгий слабый порядок, единственно разумным является исключение. Любой тип вставки или возможный другой возврат из op <скорее всего нарушит внутренние ограничения набора. </p>

Обтекание ИМХО на самом деле не нужно, поскольку поведение вашей обернутой вставки (), вероятно, будет таким же (то есть, сгенерировать исключение).

Единственное, что может сделать упаковку более привлекательной, - это какая-то неопределенность относительно того, достаточно ли хороша ваша стандартная реализация библиотеки, чтобы справиться с бросающим компаратором. Я сомневаюсь, что многие реализации стандартных библиотек сильны в безопасности исключений при этой операции.

0 голосов
/ 23 сентября 2011

Идея operator< звучит немного подозрительно.Это просто означало бы, что такие элементы упорядочены последними.x - это самый большой элемент, если x<y==false для всех y, и x<x==false всегда должно выполняться.Но если это приемлемо для вас, это нормально.

0 голосов
/ 23 сентября 2011

Если ваш std::set является деталью реализации пользовательского класса, то он должен зависеть от открытых функций-членов вашего класса, чтобы гарантировать, что недопустимые элементы не будут вставлены в ваш набор.В противном случае, если вам нужна структура данных для передачи коллекции ваших объектов, используйте std::map, предоставьте вашему классу функцию генерации ключа и поместите туда свой код обнаружения ошибок.

Помните, что элементы set,как ключи карты, должны быть неизменными относительно их порядка;Порядок на основе изменчивого состояния плохо пахнет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...