Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
volovzi
268 / 170 / 11
Регистрация: 14.03.2010
Сообщений: 501
#1

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

18.01.2013, 18:51. Просмотров 606. Ответов 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/.
Тем не менее, мне непонятно, с чем это связано, и логики в происходящем не вижу.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.01.2013, 18:51
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Странное поведение стандартной библиотеки (C++):

Подключение стандартной библиотеки с++
При подключении библиотеки &lt;QProcess&gt; следующая ошибка. Помогите ламеру :wall:

литература стандартной библиотеки C++
Вопрос - какую именно скачать книгу для изучения всех библиотек и их метадов....

Контейнер стандартной библиотеки
Привет народ ! Вот хотел узнать библиотеки в этой проге :#include &lt;iostream&gt;...

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

Использование стандартной библиотеки cstring
Добрый день. Столкнулся с маленькой проблемой хочу понять более подробные...

Странное поведение new
Объясните почему оператор new выделяет неверное количество памяти? # include...

5
soon
2545 / 1310 / 177
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
18.01.2013, 20:20 #2
Не знаю, с чем это связано, но такое поведение описано в стандарте
Цитата Сообщение от Table 98
Assertion/note pre-condition:< is defined for values of T
0
yekka
386 / 150 / 16
Регистрация: 12.05.2011
Сообщений: 450
18.01.2013, 21:30 #3
минут двадцать ломал голову над тем, что такое СБШ

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

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

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

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

я угадал? ;-)
Ну да.
0
ForEveR
В астрале
Эксперт С++
7994 / 4753 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 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 );
0
volovzi
268 / 170 / 11
Регистрация: 14.03.2010
Сообщений: 501
19.01.2013, 01:18  [ТС] #6
ForEveR
Больше всего меня просто интересует философия такой реализации оператора.

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

Добавлено через 14 минут
Наверное, формальная причина не передавать компаратор в std::lexicographical_compare состоит в том, что хотя типы компараторов совпадают, в общем случае у двух сравниваемых множеств могут быть разные экземпляры этого компаратора, потому что при конструировании класса std::set можно задавать этот самый компаратор явно, а не конструктором по-умолчанию.
И из-за этого невозможно определить, какой из этих компараторов нужно взять.
2
19.01.2013, 01:18
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.01.2013, 01:18
Привет! Вот еще темы с решениями:

Странное поведение
Здравствуйте еще раз :) Теперь возникла другая непонятка. Есть класс...

Контейнеры стандартной библиотеки шаблонов языка С + +.
Используя контейнер vector разработать программу. Создать файл test.dat в...

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

Задача по С++ Использование Стандартной Библиотеки Шаблонов.
Уважаемые программисты, помогите пожалуйста с решением такой вот задачи по С++....


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

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