Фон
Требование для компаратора по типу ключа ассоциативного контейнера (например, std:: map) заключается в том, что он налагает строгий слабый порядок на элементы типа ключа.
Для данного компаратора comp(x, y)
определим equiv(x, y) = !comp(x, y) && !comp(y, x)
.
Требования к comp(x, y)
, являющиеся строгим слабым порядком,
- Irreflexibility (
!comp(x, x)
для всехx
) - Транзитивность упорядочения (если
comp(a, b)
иcomp(b, c)
, затемcomp(a, c)
). - Транзитивность эквивалентности (если
equiv(a, b)
иequiv(b, c)
, затемequiv(a, c)
)
std::less<float>
(компаратор по умолчанию) использует operator<
, который не создает строгий слабый порядок из-за NaN
. Поскольку x < NaN
и NaN < x
являются ложными для всех x
, NaN
эквивалентно всем поплавкам под этим компаратором, это нарушает условие # 3: equiv(1.0, NaN)
и equiv(NaN, 2.0)
, но не equiv(1.0, 2.0)
. Для поплавков IEEE, кроме NaN, это строгий слабый порядок (где каждое число имеет свой собственный класс эквивалентности, за исключением 0
и -0
).
Вопрос
Означает ли это, что стандартом С++ не разрешено использовать IEEE-поплавки (и (длинные) удвоения) в качестве типа ключа в ассоциативном контейнере из-за вышеупомянутой проблемы, даже если я убеждаюсь, что NaN никогда не вставлен в контейнер? Я не совсем уверен в формулировке "элементов Key
" в стандарте - если это означает все возможные элементы или просто элементы, которые попадают в контейнер.
Примечание. Вопрос не в проблемах. усечение/округление, я скорее всего опубликую другой вопрос относительно этого в ближайшее время.
Обновление:
Вздох. Я должен был задать вопрос без указания float, я просто подумал, что это хороший пример.
Вопрос действительно: разрешено ли использовать компаратор, который налагает только строгий слабый порядок на элементы, которые помещаются в контейнер, а не все возможные экземпляры типа ключа? Пожалуйста, не просто ответьте "да" или "нет", я бы хотел, чтобы некоторые ссылки на стандартные/предыдущие обсуждения об этом/ответ от члена сообщества или что-то в этом роде.