4

I got a problem while trying to overloading a less than operator for a enum class for experimental purpose, but surprisingly it only works for unary operators i.e. ++. The compiler complaints for ambiguity:

enum class Fruit
{
    apple,
    banana,
    orange,
    pineapple,
    lemon,
};

bool operator<(Fruit l, Fruit r) 
{
    return true;
}

int main()
{
    Fruit f = Fruit::banana;
    Fruit a = Fruit::apple;
    std::cout << (a < f);
}

Compiler obviously found another less than operator in global scope, but why it would not take the overloaded one for it's an exact match?

7
  • 1
    I have also tried operator<(const Fruit& l, const Fruit& r) but got the same result. Commented Jun 26, 2016 at 7:42
  • I don't get your concern. Your operator is actually called? Commented Jun 26, 2016 at 7:44
  • Works for me. ideone.com/GO6HWR. Commented Jun 26, 2016 at 7:45
  • both gcc 4.9 and msvc 2015 has the error: error C2593: 'operator <' is ambiguous Commented Jun 26, 2016 at 7:50
  • Are you compiling your program as a C++11 program? For gcc, you will need to to use -std=c++11 in the command line. I don't know how one would enable C++11 features in VS2015. Commented Jun 26, 2016 at 7:57

2 Answers 2

4

It's a Visual C++ compiler bug which has been open since 2010 and which Microsoft apparently won't fix anytime soon.

See Visual Studio bug 529700:

I can confirm that this is a bug with Visual C++. Unfortunately it does not meet the triage bar for the current release of Visual C++ - but we will keep the issue in our database and we will look at it again during the development phase of a future release of Visual C++.


A good workaround depends on what you are trying to achieve, exactly. For example, if you want to put your Fruit into a standard container class like std::map or std::set, you might want to consider specialising std::less:

namespace std
{
    template<>
    struct less<Fruit>
    {
        bool operator()(Fruit const& lhs, Fruit const& rhs) const
        {
            // your comparison logic
        }
    };
}

std::set<Fruit> s;

Or you define a functor class for this purpose:

struct FruitComparison
{
    bool operator()(Fruit const& lhs, Fruit const& rhs) const
    {
        // your comparison logic
    }
};

std::set<Fruit, FruitComparison> s;

If you need the comparison for an algorithm, then you might want to use a lambda:

std::vector<Fruit> v;
std::sort(begin(v), end(v), [](Fruit const& lhs, Fruit const& rhs)
{
    // your comparison logic
});
Sign up to request clarification or add additional context in comments.

Comments

1

Another workaround (in addition to what Christian Hackl described), that worked for me:

1) Put your operator under a namespace (in ma case - same namespace as original enum):

namespace App
{
    enum class Fruit
    {
        apple,
        banana,
        // ...
    };

    bool operator<(Fruit l, Fruit r) 
    {
        return true;
    }
}

2) Call operator< by full name, including namespace:

namespace App
{
    void foo()
    {
        Fruit f = Fruit::banana;
        Fruit a = Fruit::apple;

        std::cout << App::operator<(a, f);
    }
}

int main()
{
    App::foo();
}

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.