A class that represents a key combination For a little game of mine I have created a Key.h file that should allow representation of a key press combination. A key combination is basically some key represented by its virtual key code stored in int _keyand the state of modifier keys - shift, control, alt and windows keys. In case that key combination is used for typing, the key also stores the character that it should produce in _c.

class Key
{
private:
    bool _shift;
    bool _ctrl;
    bool _alt;
    bool _win;
    int _key;
    char _c;

public:
    constexpr Key()
        :
        _shift(),
        _ctrl(),
        _alt(),
        _win(),
        _key(),
        _c()
    {}

    constexpr Key(const Key&amp; key)
        :
        _shift(key._shift),
        _ctrl(key._ctrl),
        _alt(key._alt),
        _win(key._win),
        _key(key._key),
        _c(key._c)
    {}

    constexpr Key(bool shift, bool ctrl, bool alt, bool win, int key, char c)
        :
        _shift(shift),
        _ctrl(ctrl),
        _alt(alt),
        _win(win),
        _key(key),
        _c(c)
    {}

    Key&amp; operator= (Key&amp; key)
    {
        _shift = key._shift;
        _ctrl = key._ctrl;
        _alt = key._alt;
        _win = key._win;
        _key = key._key;
        _c = key._c;
    }

    bool operator== (const Key&amp; key) const
    {
        return (_shift == key._shift &amp;&amp; _ctrl == key._ctrl &amp;&amp; _alt == key._alt &amp;&amp; _win == key._win &amp;&amp; _key == key._key, _c == key._c);
    }

    bool operator!= (const Key&amp; key) const
    {
        return !(*this == key);
    }
};


Are there any design flaws or some obvious things that I'm missing?
I would start by fixing the warnings, one of which is an actual bug:



[1]
Operator = not returning a value

main.cpp: In member function 'Key&amp; Key::operator=(Key&amp;)':
main.cpp:50:5: warning: no return statement in function returning non-void [-Wreturn-type]
     }
     ^
main.cpp: In member function 'bool Key::operator==(const Key&amp;) const':


Also: your operator= gets Key&amp; key instead of const Key&amp; key

Wait! don't rush to fix it. You can just eliminate it altogether and rely on the default assignment operator that does the same job ("rule of zero").



[2] using comma in the long list of equality check -- an actual bug

main.cpp:54:100: warning: left operand of comma operator has no effect [-Wunused-value]
         return ( ... &amp;&amp; _win == key._win &amp;&amp; _key == key._key, _c == key._c);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~


Wait! don't rush to fix it. We will use std::bitset so the entire operator== would become simpler.



After fixing the warnings above we can proceed for improvements.

[3] Use std::bitset for the bool flags

Instead of:

bool _shift;
bool _ctrl;
bool _alt;
bool _win;


Use:

enum SpecialKeys {SHIFT, CTRL, ALT, WIN, _SIZE_};
std::bitset&lt;SpecialKeys::_SIZE_&gt; specialKeys;




[4] No need for assignment operator and copy ctor (rule of zero).

Just use the defaults.



Proposed fixed code:

#include &lt;bitset&gt;

class Key {
    enum SpecialKeys {SHIFT, CTRL, ALT, WIN, _SIZE_};
    std::bitset&lt;SpecialKeys::_SIZE_&gt; specialKeys;
    int _key = 0;
    char _c = 0;
public:
    constexpr Key() {}
    constexpr Key(bool shift, bool ctrl, bool alt, bool win, int key, char c)
        : _key(key), _c(c)
    {
        specialKeys[SpecialKeys::SHIFT] = shift;
        specialKeys[SpecialKeys::CTRL]  = ctrl;
        specialKeys[SpecialKeys::ALT]   = alt;
        specialKeys[SpecialKeys::WIN]   = win;
    }

    bool operator== (const Key&amp; key) const
    {
        return (specialKeys == key.specialKeys &amp;&amp; _key == key._key &amp;&amp; _c == key._c);
    }

    bool operator!= (const Key&amp; key) const
    {
        return !(*this == key);
    }
};