Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
volovzi
267 / 169 / 8
Регистрация: 14.03.2010
Сообщений: 501
#1

Странное поведение стандартной библиотеки - C++

18.01.2013, 18:51. Просмотров 559. Ответов 5
Метки нет (Все метки)

Всем привет.

Обнаружил неправильное, по моему скромному мнению, поведение стандартной библиотеки.
Дело в том, что в СБШ определены операторы сравнения всех контейнеров. Больше, меньше, равно, не равно, и т.д.
Например, для класса "std::set<...>" оператор "меньше" определён следующим образом:
C++
1
2
3
4
5
6
7
8
template <class _Key, class _Compare, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
bool
operator< (const set<_Key, _Compare, _Allocator>& __x,
           const set<_Key, _Compare, _Allocator>& __y)
{
    return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end());
}
Как видно, тут используется стандартный алгоритм "std::lexicographical_compare".
Проблема в том, что в алгоритм не передаётся компаратор контейнера, то есть все элементы сравниваются на "меньше". Из-за этого невозможно сравнить два множества, для элементов которых не определён оператор "меньше", поэтому не скомпилируется следующий (абстрактный) пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <set>
 
struct point
{
    double x;
    double y;
};
 
struct point_lies_to_the_left
{
    bool operator () (const point & left, const point & right) const
    {
        return left.x < right.x;
    }
};
 
int main ()
{
    std::set<point, point_lies_to_the_left> s1{{1, 2}, {3, 4}};
    std::set<point, point_lies_to_the_left> s2{{2, 2}};
    
    s1 < s2; // Не работает.
    
    return 0;
}
То есть по логике вещей функция сравнения должна выглядеть так:
C++
1
2
3
4
5
6
7
8
template <class _Key, class _Compare, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
bool
operator< (const set<_Key, _Compare, _Allocator>& __x,
           const set<_Key, _Compare, _Allocator>& __y)
{
    return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end(), _Compare());
}
Но меня смущает, что, во-первых, такое поведение заложено для всех упорядоченных контейнеров ("сетов", "мапов"), а во-вторых, так сделано в библиотеках обоих компиляторов clang и gcc. То есть это сделано явно намеренно, и на ошибку не похоже.

Может ли кто-нибудь прокомментировать данный факт? Может, я чего-то не понимаю?

Добавлено через 16 часов 1 минуту
Нашёл строчку, сообщающую о таком поведении операторов: http://www.cplusplus.com/reference/set/set/operators/.
Тем не менее, мне непонятно, с чем это связано, и логики в происходящем не вижу.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.01.2013, 18:51     Странное поведение стандартной библиотеки
Посмотрите здесь:

C++11 новые классы стандартной библиотеки - C++
Здравствуйте. Программирую в eclipse на С++, использую С++11. Код в новом стандарте компилируется, однако мне нужен новый класс...

Странное поведение string - C++
Здравствуйте. Сейчас я пытаюсь скомпилировать под Windows проект, который ранее писался под Linux. Делаю я это с помощью MinGW от...

Странное поведение (сдвиг) - C++
Здравствуйте.Прошу помочь с задачкой. Программа , должна &quot;сдвигать&quot; данные в один бит(128), но при вызове функции с разными параметрами,...

Странное поведение в коде - C++
Есть два класса: ArrayList&lt;T&gt; и Array&lt;T&gt; (реализация в конце поста). И есть такой код: ArrayList&lt;int&gt; list = { 1, 2, 3 }; ...

Странное поведение кода - C++
int x; cout &lt;&lt; (x = 1) + (x = 2) + (x = 3); У меня выводит 7 (вместо 6). Почему?!?!

Странное поведение строки - C++
Есть класс со связным списком(в связных списках символы)(файл1). Перегружаю оператор сложения для объектов этих классов так, чтобы оператор...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
soon
2540 / 1305 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
18.01.2013, 20:20     Странное поведение стандартной библиотеки #2
Не знаю, с чем это связано, но такое поведение описано в стандарте
Цитата Сообщение от Table 98
Assertion/note pre-condition:< is defined for values of T
yekka
385 / 149 / 8
Регистрация: 12.05.2011
Сообщений: 450
18.01.2013, 21:30     Странное поведение стандартной библиотеки #3
минут двадцать ломал голову над тем, что такое СБШ

есть версия, что это "стандартная библиотека шаблонов"

я угадал? ;-)
volovzi
267 / 169 / 8
Регистрация: 14.03.2010
Сообщений: 501
19.01.2013, 00:16  [ТС]     Странное поведение стандартной библиотеки #4
Цитата Сообщение от soon Посмотреть сообщение
Не знаю, с чем это связано, но такое поведение описано в стандарте
То, что так написано в стандарте, я уже понял. Меня интересует логика происходящего.
Ну то есть мне на интуитивном уровне кажется, что если я явно определил некий компаратор для элементов множества, то все операции, происходящие с этим множеством, будут реализованы через этот компаратор.
Однако в библиотеке не так. И получается, что если у меня не определён оператор "меньше" для элемента, то я не могу лексикографически сравнить два множества. Почему сделано именно так? Объяснения я не нашёл.

Цитата Сообщение от yekka Посмотреть сообщение
минут двадцать ломал голову над тем, что такое СБШ

есть версия, что это "стандартная библиотека шаблонов"

я угадал? ;-)
Ну да.
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
19.01.2013, 00:48     Странное поведение стандартной библиотеки #5
volovzi, Что мешает вызвать lexicographical_compare напрямую?
C++
1
2
3
4
template <class InputIterator1, class InputIterator2, class Compare>
  bool lexicographical_compare ( InputIterator1 first1, InputIterator1 last1,
                                 InputIterator2 first2, InputIterator2 last2,
                                 Compare comp );
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.01.2013, 01:18     Странное поведение стандартной библиотеки
Еще ссылки по теме:

Странное поведение транслятора - C++
В следуюшем примере код компилируется нормально, но объект класса b не содается (пробывал на Visual studio 10 и на Borland builder 5), что...

Странное поведение указателей - C++
Здравствуйте, может кто-нибудь объяснить столь странное поведение указателя. Вот код. int main() { const int Width = 3; ...

Странное поведение программы - C++
Перечитываю Герберт Шилдт: С++ базовый курс. Простая программа: #include &lt;iostream&gt; using namespace std; int main() { ...

Странное поведение присваивания - C++
class Lexem { public: uint id; uint value; uint line; uint pos; bool operator==(int a){ return a...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
volovzi
267 / 169 / 8
Регистрация: 14.03.2010
Сообщений: 501
19.01.2013, 01:18  [ТС]     Странное поведение стандартной библиотеки #6
ForEveR
Больше всего меня просто интересует философия такой реализации оператора.

А во-вторых, проблема в том, что у меня ссылки на сеты хранятся в мапе, поэтому я хочу уметь сравнивать сеты. При этом я не хочу определять оператор "меньше" для элементов сета.

Добавлено через 14 минут
Наверное, формальная причина не передавать компаратор в std::lexicographical_compare состоит в том, что хотя типы компараторов совпадают, в общем случае у двух сравниваемых множеств могут быть разные экземпляры этого компаратора, потому что при конструировании класса std::set можно задавать этот самый компаратор явно, а не конструктором по-умолчанию.
И из-за этого невозможно определить, какой из этих компараторов нужно взять.
Yandex
Объявления
19.01.2013, 01:18     Странное поведение стандартной библиотеки
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru