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

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

Восстановить пароль Регистрация
 
volovzi
266 / 168 / 8
Регистрация: 14.03.2010
Сообщений: 501
18.01.2013, 18:51     Странное поведение стандартной библиотеки #1
Всем привет.

Обнаружил неправильное, по моему скромному мнению, поведение стандартной библиотеки.
Дело в том, что в СБШ определены операторы сравнения всех контейнеров. Больше, меньше, равно, не равно, и т.д.
Например, для класса "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++ WinAPI
C++ Странное поведение
Странное поведение Builder XE C++ Builder
странное поведение указателя C++
Странное поведение! C++ Builder
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
soon
 Аватар для soon
2536 / 1301 / 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
384 / 148 / 8
Регистрация: 12.05.2011
Сообщений: 450
18.01.2013, 21:30     Странное поведение стандартной библиотеки #3
минут двадцать ломал голову над тем, что такое СБШ

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

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

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

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

я угадал? ;-)
Ну да.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 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 );
volovzi
266 / 168 / 8
Регистрация: 14.03.2010
Сообщений: 501
19.01.2013, 01:18  [ТС]     Странное поведение стандартной библиотеки #6
ForEveR
Больше всего меня просто интересует философия такой реализации оператора.

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

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

Текущее время: 07:46. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru