Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ if (mask1 & Value2) { // if Value2 flag is set
```

## Description

**Disclaimer: docs are currently out of sync a little bit**

``` c++
template <class E> class flags;
```
Expand All @@ -56,7 +59,8 @@ underlying_type|The integer type that is used as representation of `flags`|Equiv
#### Constructors and assignment operators
Name |Description
-----------------------------|-----------
`flags()` |Default contructor (all flags are unset)
`flags()` |Default contructor, keeps object uninitialized (note: object may contain garbage)
`flags(empty_t)` |Unsets all flags
`flags(flags::enum_type)` |Sets flag denoted by the parameter
`flags(const flags&)` |Copy constructor
`flags(flags&&)` |Move constructor
Expand Down
102 changes: 31 additions & 71 deletions include/flags/flags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace flags {


constexpr struct empty_t {
constexpr empty_t() noexcept {}
constexpr empty_t() noexcept {}
} empty;


Expand Down Expand Up @@ -97,9 +97,17 @@ template <class E> struct flags {

constexpr bool operator!() const noexcept { return !val_; }

flags operator~() const noexcept { return flags(~val_); }
friend constexpr bool operator==(flags fl1, flags fl2) {
return fl1.val_ == fl2.val_;
}

friend constexpr bool operator!=(flags fl1, flags fl2) {
return fl1.val_ != fl2.val_;
}


constexpr flags operator~() const noexcept { return flags(~val_); }

flags &operator|=(const flags &fl) noexcept {
val_ |= fl.val_;
return *this;
Expand Down Expand Up @@ -131,6 +139,18 @@ template <class E> struct flags {
return *this;
}

friend constexpr flags operator|(flags f1, flags f2) noexcept {
return flags{f1.val_ | f2.val_};
}

friend constexpr flags operator&(flags f1, flags f2) noexcept {
return flags{f1.val_ & f2.val_};
}

friend constexpr flags operator^(flags f1, flags f2) noexcept {
return flags{f1.val_ ^ f2.val_};
}


void swap(flags &fl) noexcept { std::swap(val_, fl.val_); }

Expand All @@ -153,7 +173,7 @@ template <class E> struct flags {
}


bool empty() const noexcept { return !val_; }
constexpr bool empty() const noexcept { return !val_; }

size_type size() const noexcept {
return std::distance(this->begin(), this->end());
Expand All @@ -165,13 +185,13 @@ template <class E> struct flags {
iterator begin() const noexcept { return cbegin(); }
iterator cbegin() const noexcept { return iterator{val_}; }

iterator end() const noexcept { return cend(); }
iterator cend() const noexcept { return {}; }
constexpr iterator end() const noexcept { return cend(); }
constexpr iterator cend() const noexcept { return {}; }


iterator find(enum_type e) const noexcept { return {val_, e}; }
constexpr iterator find(enum_type e) const noexcept { return {val_, e}; }

size_type count(enum_type e) const noexcept {
constexpr size_type count(enum_type e) const noexcept {
return find(e) != end() ? 1 : 0;
}

Expand Down Expand Up @@ -256,67 +276,7 @@ template <class E> struct flags {


template <class E>
constexpr flags<E> operator|(flags<E> f1, flags<E> f2) noexcept {
return f1 |= f2;
}

template <class E>
constexpr flags<E> operator|(flags<E> f, E e) noexcept {
return f |= e;
}

template <class E>
constexpr flags<E> operator|(E e, flags<E> f) noexcept {
return f |= e;
}


template <class E>
constexpr flags<E> operator&(flags<E> f1, flags<E> f2) noexcept {
return f1 &= f2;
}

template <class E>
constexpr flags<E> operator&(flags<E> f, E e) noexcept {
return f &= e;
}

template <class E>
constexpr flags<E> operator&(E e, flags<E> f) noexcept {;
return f &= e;
}


template <class E>
constexpr flags<E> operator^(flags<E> f1, flags<E> f2) noexcept {
return f1 ^= f2;
}

template <class E>
constexpr flags<E> operator^(flags<E> f, E e) noexcept {
return f ^= e;
}

template <class E>
constexpr flags<E> operator^(E e, flags<E> f) noexcept {
return f ^= e;
}


template <class E>
constexpr bool operator==(const flags<E> &fl1, const flags<E> &fl2) noexcept {
return fl1.underlying_value() == fl2.underlying_value();
}


template <class E>
constexpr bool operator!=(const flags<E> &fl1, const flags<E> &fl2) noexcept {
return fl1.underlying_value() != fl2.underlying_value();
}


template <class E>
constexpr void swap(flags<E> &fl1, flags<E> &fl2) noexcept { fl1.swap(fl2); }
void swap(flags<E> &fl1, flags<E> &fl2) noexcept { fl1.swap(fl2); }


} // namespace flags
Expand All @@ -326,23 +286,23 @@ template <class E>
constexpr auto operator|(E e1, E e2) noexcept
-> typename std::enable_if<flags::is_flags<E>::value,
flags::flags<E>>::type {
return flags::flags<E>{e1} |= e2;
return flags::flags<E>(e1) | e2;
}


template <class E>
constexpr auto operator&(E e1, E e2) noexcept
-> typename std::enable_if<flags::is_flags<E>::value,
flags::flags<E>>::type {
return flags::flags<E>{e1} &= e2;
return flags::flags<E>(e1) & e2;
}


template <class E>
constexpr auto operator^(E e1, E e2) noexcept
-> typename std::enable_if<flags::is_flags<E>::value,
flags::flags<E>>::type {
return flags::flags<E>{e1} ^= e2;
return flags::flags<E>(e1) ^ e2;
}


Expand Down
2 changes: 1 addition & 1 deletion include/flags/iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class FlagsIterator {
using impl_type = typename flags_type::impl_type;


explicit FlagsIterator(impl_type uv) noexcept : mask_(1), uvalue_(uv) {
explicit FlagsIterator(impl_type uv) noexcept : uvalue_(uv), mask_(1) {
if (!(mask_ & uvalue_)) { nextMask(); }
}

Expand Down
11 changes: 10 additions & 1 deletion test/Jamroot
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import testing ;


project flags_tests
: requirements <warnings>all
<cxxflags>-std=c++11
Expand All @@ -18,4 +19,12 @@ unit-test main-test
: main-test.cpp boost_utf
: <define>BOOST_TEST_DYN_LINK
<define>BOOST_TEST_MODULE=enum_flags
;
;


compile should-compile.cpp ;


for src in [ glob shouldnt-compile/*.cpp ] {
compile-fail $(src) ;
}
14 changes: 14 additions & 0 deletions test/common.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef ENUM_CLASS_TEST_COMMON_HPP
#define ENUM_CLASS_TEST_COMMON_HPP


#include <flags/flags.hpp>


enum class Enum : int {One = 1, Two = 2, Four = 4, Eight = 8};
ALLOW_FLAGS_FOR_ENUM(Enum)

using Enums = flags::flags<Enum>;


#endif // ENUM_CLASS_TEST_COMMON_HPP
8 changes: 1 addition & 7 deletions test/main-test.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
#include <flags/flags.hpp>
#include "common.hpp"

#include <vector>

#include <boost/test/unit_test.hpp>


enum class Enum : int {One = 1, Two = 2, Four = 4, Eight = 8};
ALLOW_FLAGS_FOR_ENUM(Enum)

using Enums = flags::flags<Enum>;


BOOST_AUTO_TEST_CASE(set_underlying_value) {
Enums result;
constexpr int random_number = 87;
Expand Down
Loading