3

this is my first try to use enum classes for my projects, but I have the problem that I can't compile my code if the enum class is placed inside of another class. I try to define the operator overloading like my example and I try to do it outside, too. All works fine if I place the enum class outside the class. Whats wrong? How to overloading the operator if I what to use it placed in an class?

#include <cstdint>

namespace MyNamespace
{
    class MyClass
    {
    public:
        enum class MyEnum_t
        {
            VALUE_0 = 0x0,
            VALUE_1 = 0x1,
            VALUE_2 = 0x2,
            VALUE_3 = 0x4,
            VALUE_4 = 0x8 
       };

        inline MyEnum_t &operator|(MyEnum_t lhs, MyEnum_t rhs)
        {
            return static_cast<MyEnum_t>(static_cast<std::uint8_t>(lhs) | static_cast<std::uint8_t>(rhs));
        }
}

int main()
{
    MyNamespace::MyClass::MyEnum_t test = MyNamespace::MyClass::MyEnum_t::VALUE_0;

    test = MyNamespace::MyClass:MyEnum_t::VALUE_1 | MyNamespace::MyClass::MyEnum_t::VALUE_2;

    return 0;
}
3
  • 2
    "I can't compile my code", so provide error message. Commented May 9, 2018 at 13:25
  • 3
    Your class definition is missing a closing brace and a semi-colon. It's better to sort these things out before posting, so the code exhibits just the problem you are asking about. Commented May 9, 2018 at 13:26
  • 3
    MyClass::MyEnum_t &operator|(MyClass::MyEnum_t lhs, MyClass::MyEnum_t rhs) should be placed outside the class. Commented May 9, 2018 at 13:26

4 Answers 4

3

The enum class can be inside another class, but the operator definition must be at namespace scope.

Also note that the operator is computing a new value and as such, it cannot return a reference, as there would be nothing to which the reference could bind. It should return by value instead.

In total:

namespace MyNamespace
{
    class MyClass
    {
    public:
        enum class MyEnum_t
        {
            VALUE_0 = 0x0,
            VALUE_1 = 0x1,
            VALUE_2 = 0x2,
            VALUE_3 = 0x4,
            VALUE_4 = 0x8 
       };
    };

    inline MyClass::MyEnum_t operator|(MyClass::MyEnum_t lhs, MyClass::MyEnum_t rhs)
    {
       return static_cast<MyEnum_t>(static_cast<std::uint8_t>(lhs) | static_cast<std::uint8_t>(rhs));
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Might wanna fix the return type of the operator
I agree with you that this must be the correct way to do it but it doesn't compile. If I try to compile it I got the message: "error: ‘MyEnum_t’ does not name a type" If I try to fix the return value adding "MyClass::" I got: "error: cannot bind non-const lvalue reference of type ‘MyNamespace::MyClass::MyEnum_t&’ to an rvalue of type ‘MyNamespace::MyClass::MyEnum_t’"
@Mnemonic That's because of the reference, as StoryTeller correctly pointed out. Answer edited.
@Angew One thing was wrong in your solution. The scope of the return value. After fixing that its compiles. Thank you.
@Mnemonic "One thing was wrong in your solution": well, it was just copy-pasted from the Q, so it wasn't really "my" solution. I just didn't notice, because the & is placed in an unusual place (it's more commonly placed by the type, not by the function name). Anyway, that's what I mentioned as edited in the answer.
3

I would write it as:

class MyClass
{
public:
    enum class MyEnum_t
    {
        VALUE_0 = 0x0,
        VALUE_1 = 0x1,
        VALUE_2 = 0x2,
        VALUE_3 = 0x4,
        VALUE_4 = 0x8,
    };

    friend MyEnum_t operator|(MyEnum_t lhs, MyEnum_t rhs)
    {
        using UT = std::underlying_type<MyEnum_t>::type;
        return static_cast<MyEnum_t>(static_cast<UT>(lhs) | static_cast<UT>(rhs));
    }
};

This way, it no longer matters whether or not MyClass is in a namespace, and the correct underlying_type is used to perform the bitwise math.

Comments

1

Fixed code for the operator:

inline MyClass::MyEnum_t operator|(MyClass::MyEnum_t lhs, MyClass::MyEnum_t rhs)
{
    return static_cast<MyClass::MyEnum_t>(static_cast<std::uint8_t>(lhs) | static_cast<std::uint8_t>(rhs));
}

Comments

0

As you wrote your following main() code line:

test = MyNamespace::MyClass:MyEnum_t::VALUE_1 | MyNamespace::MyClass::MyEnum_t::VALUE_2;

It will expect namespace operator, so the operator should be placed outside the MyClass (but within the MyNamespace):

MyClass::MyEnum_t operator|(MyClass::MyEnum_t lhs, MyClass::MyEnum_t rhs)
{
    return static_cast<MyClass::MyEnum_t>(static_cast<std::uint8_t>(lhs) | static_cast<std::uint8_t>(rhs));
}

also, as stated in above answer you can not return a temporary memory (as reference), so either return by-value or define static variable in the operator and return it.

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.