std :: set insert, не учитывающий пользовательский компаратор.(возможная ошибка компилятора?) - PullRequest
0 голосов
/ 14 мая 2018

Я обнаружил, что std::inserter на std::map<T, C> не всегда соблюдает пользовательский компаратор, а скорее иногда возвращается к значению по умолчанию operator< / std::less.У кого-нибудь есть опыт с тем, почему это может быть?Я чувствую, что это может быть ошибка компилятора, учитывая спорадический характер.В частности, у меня есть такая функция:

template <typename T, typename C>
std::set<T, C> operator|(const std::set<T, C> &lhs, const std::set<T, C> &rhs)
{
  std::set<T, C> out;
  std::set_union(lhs.begin(), lhs.end(),
                 rhs.begin(), rhs.end(),
                 inserter(out, out.end()));
  return out;
}

Но это не всегда использует мой собственный компаратор C, и иногда (я знаю, я тоже хотел бы найти образец) просто используюstd::less вместо.Если я заменю его на maunal-конструкцию std::insert_iterator<std::set<T, C>>, все будет работать правильно:

template <typename T, typename C>
std::set<T, C> operator|(const std::set<T, C> &lhs, const std::set<T, C> &rhs)
{
  std::set<T, C> out;
  std::set_union(lhs.begin(), lhs.end(),
                 rhs.begin(), rhs.end(),
                 std::insert_iterator<std::set<T, C>>(out, out.end()));
  return out;
}

Я чувствую, что это может быть ошибкой компилятора (gcc версии 7.3.0), потому что ссылка доступна на http://en.cppreference.com/w/cpp/iterator/inserter описывает inserter для простого делегирования insert_iterator:

template< class Container >
std::insert_iterator<Container> inserter( Container& c, typename Container::iterator i )
{
    return std::insert_iterator<Container>(c, i);
}

Кроме того, официальный стандарт C ++, раздел 24.5.2.5 (доступен через http://www.open -std.org /jtc1 / sc22 / wg21 / docs / paper / 2013 / n3690.pdf , стр. 859) определяет определение вставщика как возвращающее итератор вставки того же типа, который передан в первом аргументе:

template <class Container>
      insert_iterator<Container> inserter(Container& x, typename Container::iterator i);

Что здесь явно не происходит, поскольку возвращаемое insert_iterator относится к классу типа std::set<T, C = std::less<T>>, а не std::set<T, C>.

Существует ли объяснение этому, кроме ошибки компилятора?

1 Ответ

0 голосов
/ 14 мая 2018

«возможная ошибка компилятора» для C ++ означает, что «это может быть Lupus» для House MD.

При этом, следуя документации , вы, похоже, используете версию 1) функции, которая четко гласит:

1) Элементы сравниваются с помощью оператора <, и диапазоны должны быть отсортированы по одному и тому же. </p>

Что вам следует сделать, это передать свой компаратор на std::set_union, согласно версии 3) функции.

Итак, настоящая загадка: зачем используется ваш компараторвообще иногда.Тем не менее, поскольку вы не соблюдаете предварительные условия функции:

, диапазоны должны быть отсортированы по одному и тому же.

Тогда не определено ожидаемое поведение,поэтому поведение не является «неправильным».

...