Они оба запрещены стандартом.
Для (упорядоченных) ассоциативных контейнеров определение строгого слабого порядка (25.4 / 4) гласит:
Если мы определим equiv(a, b)
как !comp(a, b) && !comp(b, a)
, то
требования, чтобы comp
и equiv
были транзитивными отношениями ...
equiv(a, b) && equiv(b, c)
подразумевает equiv(a, c)
Это не работает для a = 0.0, b = NaN, c = 1.0, comp = std::less<double>()
Для неупорядоченных контейнеров 23.2.5 / 3 говорит, что предикат равенства Pred
«вызывает отношение эквивалентности для значений типа Key
». Отношения эквивалентности рефлексивны, и std::equal_to<double>()(NaN,NaN)
ложно, поэтому equal_to<double>()
не является отношением эквивалентности.
Кстати, использование контейнеров на двойнике немного страшно, так же как сравнение двойников на равенство всегда немного страшно. Вы никогда не знаете, что вы получите в наименее значимом кусочке.
Что-то, что я всегда считал немного странным, - это то, что стандарт выражает требования в терминах ключа type , а не в терминах фактических значений ключа, добавляемых в контейнер. Я полагаю, что вы можете прочитать это как не гарантирующее, что map<double, int>
определил поведение вообще, если реализация поддерживает NaN, независимо от того, добавляете ли вы NaN к экземпляру или нет. На практике, однако, реализация std::map
не может каким-либо образом вызвать NaN
из своего заднего кармана и попытаться сравнить его, она только когда-либо сравнивает значения ключей, переданные в экземпляр. Так что все должно быть в порядке (если немного страшно), если вы избегаете добавления NaN.
Буду очень признателен за комментарии о том, как работают другие языки
ключи с плавающей запятой в ассоциативных контейнерах
Несколько быстрых экспериментов в Python (где set
и dict
являются неупорядоченными ассоциативными контейнерами, которые содержат ключи и значения по ссылке) предполагают, что NaN обрабатываются как объекты, которые имеют неравные значения, даже если они "одинаковы" NaN ", но тот же объект nan может быть снова найден по идентичности. Насколько я видел, контейнеры, похоже, не мешают содержать несколько nans или смесь nans и других значений:
>>> thing = set()
>>> nan = float('nan')
>>> nan
nan
>>> thing.add(nan)
>>> thing.add(nan)
>>> thing
set([nan])
>>> thing = dict()
>>> thing[nan] = 1
>>> thing[nan] = 2
>>> thing[nan]
2
>>> nan2 = float('nan')
>>> thing[nan2] = 3
>>> thing
{nan: 2, nan: 3}
>>> thing = set()
>>> thing.add(nan)
>>> thing.add(nan2)
>>> thing
set([nan, nan])
>>> thing = dict()
>>> thing[nan] = 1
>>> thing[nan2] = 2
>>> thing[0] = 3
>>> thing
{nan: 1, nan: 2, 0: 3}
>>> thing.keys()
[nan, nan, 0]
>>> thing.values()
[1, 2, 3]
>>> thing[0]
3
>>> thing[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 1