3

So I created a custom Comparator for an std::set. Code as follows:

class Identifier
{
    std::string nameID;

public:
    std::string NameID() const
    {
        return this->nameID;
    }
};

class IdentifierSorter
{
    static bool icompare_pred(unsigned char a, unsigned char b)
    {
        return std::tolower(a) == std::tolower(b);
    }

    bool icompare(const std::string& a, const std::string& b)
    {
        return std::lexicographical_compare(a.begin(), a.end(),
            b.begin(), b.end(), icompare_pred);
    }

    bool operator()(const Identifier& id1, const Identifier& id2)
    {
        std::string id1n = id1.NameID();
        std::string id2n = id2.NameID();
        return icompare(id1n, id2n);
    }
};

....

std::set<Identifier, IdentifierSorter> Identifiers;

Everything works fine until I try to do this:

auto it = Identifiers.find(someIdentifier);

I get a runtime error that reads:

Program: C:\Windows\system32\MSVCP120D.dll
File: c:\program files (x86)\microsoft visual studio   12.0\vc\include\xutility
Line: 2941

Expression: invalid operator<

I'm not sure what is wrong. Did I implement the Comparator incorrectly?

2
  • You should have reduced that code to a minimal example, it has both code that is too much and code that is missing or broken. As it stands, it is considered off-topic therefore. Commented Feb 14, 2015 at 21:28
  • strings contain chars and not unsigned chars. Use const references of strings to avoid copies. Commented Feb 14, 2015 at 21:28

2 Answers 2

2

Your code doesn't work because your comparison provides something like equality, while the algorithm (lexicographical_compare) needs a relation.

return std::tolower(a) < std::tolower(b);

BTW: Look at where that error message comes from. It should tell you that the predicate is invalid. Search the web for "strict weak ordering", that should give you further hints how and why this works.

Sign up to request clarification or add additional context in comments.

3 Comments

That wouldn't prevent it from compiling.
He gets a runtime error from a "checked" standardlib, I guess.
Interesting, I hadn't noticed that the OP was referring to a runtime error. So you may well be correct, in that case!
2

The methods of predicate have to be public:

class IdentifierSorter
{
    public:

    static bool icompare_pred(unsigned char a, unsigned char b)
    {
        return std::tolower(a) == std::tolower(b);
    }

    bool icompare(const std::string& a, const std::string& b)
    {
        return std::lexicographical_compare(a.begin(), a.end(),
            b.begin(), b.end(), icompare_pred);
    }

    bool operator()(const Identifier& id1, const Identifier& id2)
    {
        std::string id1n = id1.NameID();
        std::string id2n = id2.NameID();
        return icompare(id1n, id2n);
    }
};

Other than that predicate should behave like std::less, that is instead of

static bool icompare_pred(unsigned char a, unsigned char b)
{
    return std::tolower(a) == std::tolower(b);
}

you want

static bool icompare_pred(unsigned char a, unsigned char b)
{
    return std::tolower(a) < std::tolower(b);
                       // ^^^
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.