Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one use an enum class as a set of flags?

Tags:

c++

c++11

Let's say I have a set of flags and a class like this:

/// <summary>Options controlling a search for files.</summary>
enum class FindFilesOptions : unsigned char
{
    LocalSearch = 0,
    RecursiveSearch = 1,
    IncludeDotDirectories = 2
};

class FindFiles : boost::noncopyable
{
    /* omitted */
public:
    FindFiles(std::wstring const& pattern, FindFilesOptions options);
    /* omitted */
}

and I want a caller to be able to select more than one option:

FindFiles handle(Append(basicRootPath, L"*"),
    FindFilesOptions::RecursiveSearch | FindFilesOptions::IncludeDotDirectories);

Is it possible to support this in a strongly-typed way with C++11 enum class, or do I have to revert to untyped enumerations?

(I know the caller could static_cast to the underlying type and static_cast back, but I don't want the caller to have to do that)

like image 499
Billy ONeal Avatar asked Aug 31 '13 23:08

Billy ONeal


1 Answers

It is certainly possible to use enum classes for bitmaps. It is, unfortunately, a bit painful to do so: You need to define the necessary bit operations on your type. Below is an example how this could look like. It would be nice if the enum classes could derive from some other type which could live in a suitable namespace defining the necessary operator boilerplate code.

#include <iostream>
#include <type_traits>

enum class bitmap: unsigned char
{
    a = 0x01,
    b = 0x02,
    c = 0x04
};

bitmap operator& (bitmap x, bitmap y)
{
    typedef std::underlying_type<bitmap>::type uchar;
    return bitmap(uchar(x) & uchar(y));
}

bitmap operator| (bitmap x, bitmap y)
{
    typedef std::underlying_type<bitmap>::type uchar;
    return bitmap(uchar(x) | uchar(y));
}

bitmap operator^ (bitmap x, bitmap y)
{
    typedef std::underlying_type<bitmap>::type uchar;
    return bitmap(uchar(x) ^ uchar(y));
}

bool test(bitmap x)
{
    return std::underlying_type<bitmap>::type(x);
}

int main()
{
    bitmap v = bitmap::a | bitmap::b;
    if (test(v & bitmap::a)) {
        std::cout << "a ";
    }
    if (test(v & bitmap::b)) {
        std::cout << "b ";
    }
    if (test(v & bitmap::c)) {
        std::cout << "c ";
    }
    std::cout << '\n';
}
like image 85
Dietmar Kühl Avatar answered Oct 04 '22 19:10

Dietmar Kühl