Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3842962
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 19, 20262026-05-19T15:52:10+00:00 2026-05-19T15:52:10+00:00

Background The requirement for a comparator on the key type of an associative container

  • 0

Background

The requirement for a comparator on the key type of an associative container (for example std::map) is that it imposes a strict weak order on the elements of the key type.

For a given comparator comp(x, y) we define equiv(x, y) = !comp(x, y) && !comp(y, x).
The requirements for comp(x, y) being a strict weak order are

  1. Irreflexibility (!comp(x, x) for all x)
  2. Transitivity of the ordering (if comp(a, b) and comp(b, c) then comp(a, c)).
  3. Transitivity of equivalence (if equiv(a, b) and equiv(b, c) then equiv(a, c))

std::less<float> (the default comparator) uses operator<, which does not create a strict weak order because of NaN. Because x < NaN and NaN < x are false for all x, NaN is equivalent to all floats under this comparator, this breaks condition #3: equiv(1.0, NaN) and equiv(NaN, 2.0) but not equiv(1.0, 2.0). For IEEE floats except NaN, it is a strict weak order (where each number has its own equivalence class except for 0 and -0).

The question

Does this mean that one is not allowed by the C++ standard to use IEEE floats (and (long) doubles) as a key type in an associative container because of the above issue, even if I make sure that NaN never gets inserted into the container? I’m not quite sure about the “elements of Key” wording in the standard—if it means all possible elements or just the elements that end up in the container.

Note: The question is not about issues wrt. truncation/rounding, I’ll likely post a different question regarding that soon.

Update:

Sigh. I should’ve posed the question without specifying float, I just thought it was a nice example.

The question really is: Is it allowed to use a comparator that only imposes a strict weak order on the elements that get put into the container, not all possible instances of the key type? Please don’t just answer “yes” or “no”, I’d like some references to the standard / prior discussions about this / an answer from a commitee member or something.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-19T15:52:11+00:00Added an answer on May 19, 2026 at 3:52 pm

    I suspect the restrictions should be taken as referring to the relation’s behavior on the values actually used as keys, not necessarily on all values of the type. Don’t have time at the moment to go through the standard looking for “smoking gun” language that refers to actual container elements rather than all values of the type.

    Similar case: what if a comparator (for a container of pointers or smart pointers) calls a virtual function, and somebody links a derived class of the type it compares, which overrides the virtual function in a way that makes the comparator not a strict weak order? Does the program become undefined even if nobody ever actually uses that derived class?

    If in doubt, you can support NaN with a comparator that is a strict weak order:

    bool operator()(double a, double b) {
        if ((a == a) && (b == b)) {
            return a < b;
        }
        if ((a != a) && (b != b)) return false;
        // We have one NaN and one non-NaN.
        // Let's say NaN is less than everything
        return (a != a)
    }
    

    The last two lines “optimize” to return (b == b);, although I’m not sure the comment optimizes with it.

    I think Tomalak has convinced me the language does say the whole type needs to be ordered.

    This makes little sense, since a map doesn’t conjure values out of nowhere, it only uses values that it’s given (and copies of them), but the question is about the rules, and them’s the rules as far as I know. C++0x is the same. I wonder if there’s a defect report, or any point submitting one.

    It’s also annoying in that on (very rare) systems where std::less is slow for pointers, you can’t use < as the comparator in a map of pointers, even if you know that the pointers are all to elements of the same array. Shame.

    Another option is to use the following class as the key type, so keys are checked for NaN only on entry to the map, not on every comparison as above.

    struct SaneDouble {
        double value;
        SaneDouble (double d) : value(d) {
            if (d != d) throw std::logic_error();
        }
        static friend bool operator<(SaneDouble lhs, SaneDouble rhs) {
            return lhs.value < rhs.value;
        }
        // possibly a conversion to double
    };
    

    This raises another question – clearly someone could create a SaneDouble and then set its value to NaN (assuming the implementation lets them get one from somewhere without crashing). So are “elements of SaneDouble” strict-weak-ordered or not? Does my half-hearted attempt to create a class invariant in the constructor make my program undefined even if nobody actually breaks the invariant, simply because they could and therefore the results of doing so are “elements of SaneDouble”? Is it really the intention of the standard that the program’s behavior is defined if and only if value is marked private? Does the standard actually define anywhere what “the elements” of a type are?

    I wonder whether we should interpret “elements of Key” to mean that the comparator induces a strict weak order on some elements of Key. Presumably including the ones actually used. “I have doughnuts” doesn’t mean I have every doughnut. It’s a stretch, though.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a requirement to create a background processor that works only when the
I have a requirement that, I have to remove the background of the element
Background: I am working on an Android Honeycomb (v3.0) application that has a requirement
I have a requirement to build features that perform certain background tasks on a
My specific requirement is an app that is in the background, being notified that
Background: We're building an application that allows our customers to supply data in a
Background: I would like to dismiss a modalView that I have presented earlier and
Giving small background to my requirement and what i had accomplished so far: There
As per clients requirement, i have added a background music to webpage. I have
BACKGROUND : I now understand how to write a C# application that can monitor

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.