Add FlagsValueType
This commit is contained in:
parent
dbfd63e8d2
commit
ac63b5af85
@ -47,6 +47,15 @@ namespace value_type {
|
||||
* - val % scalar (returns val)
|
||||
* - val / val (returns scalar)
|
||||
* - val % val (returns scalar)
|
||||
*
|
||||
* FlagsValueType: Use this if you want a value type for bitfields (i.e. flags).
|
||||
* Additionally to what IdValueType offers, this also defines:
|
||||
* - val |= val (returns val)
|
||||
* - val &= val (returns val)
|
||||
* - val ^= val (returns val)
|
||||
* - val | val (returns val)
|
||||
* - val & val (returns val)
|
||||
* - val ^ val (returns val)
|
||||
*/
|
||||
template <class ConcreteType, class UnderlyingType>
|
||||
class IdValueType {
|
||||
@ -209,6 +218,46 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class ConcreteType, class UnderlyingType>
|
||||
class FlagsValueType : public IdValueType<ConcreteType, UnderlyingType> {
|
||||
protected:
|
||||
using IdValueType<ConcreteType, UnderlyingType>::IdValueType;
|
||||
|
||||
public:
|
||||
|
||||
constexpr ConcreteType& operator&=(ConcreteType rhs) noexcept(noexcept(*std::declval<UnderlyingType*>() &= std::declval<UnderlyingType>())) {
|
||||
this->value_ &= rhs.value_;
|
||||
return *static_cast<ConcreteType*>(this);
|
||||
}
|
||||
|
||||
constexpr ConcreteType& operator|=(ConcreteType rhs) noexcept(noexcept(*std::declval<UnderlyingType*>() |= std::declval<UnderlyingType>())) {
|
||||
this->value_ |= rhs.value_;
|
||||
return *static_cast<ConcreteType*>(this);
|
||||
}
|
||||
|
||||
constexpr ConcreteType& operator^=(ConcreteType rhs) noexcept(noexcept(*std::declval<UnderlyingType*>() ^= std::declval<UnderlyingType>())) {
|
||||
this->value_ ^= rhs.value_;
|
||||
return *static_cast<ConcreteType*>(this);
|
||||
}
|
||||
|
||||
constexpr ConcreteType operator~() noexcept(noexcept(~*std::declval<UnderlyingType*>())) {
|
||||
return ConcreteType(~this->value_);
|
||||
}
|
||||
|
||||
friend constexpr ConcreteType operator&(ConcreteType lhs, ConcreteType rhs) noexcept(noexcept(std::declval<ConcreteType>() &= std::declval<ConcreteType>())) {
|
||||
return lhs &= rhs;
|
||||
}
|
||||
|
||||
friend constexpr ConcreteType operator|(ConcreteType lhs, ConcreteType rhs) noexcept(noexcept(std::declval<ConcreteType>() |= std::declval<ConcreteType>())) {
|
||||
return lhs |= rhs;
|
||||
}
|
||||
|
||||
friend constexpr ConcreteType operator^(ConcreteType lhs, ConcreteType rhs) noexcept(noexcept(std::declval<ConcreteType>() ^= std::declval<ConcreteType>())) {
|
||||
return lhs ^= rhs;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define MESSMER_FSPP_FSINTERFACE_DIR_H_
|
||||
|
||||
#include <cpp-utils/pointer/unique_ref.h>
|
||||
#include <cpp-utils/value_type/ValueType.h>
|
||||
#include <string>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
using cpputils::value_type::IdValueType;
|
||||
using cpputils::value_type::OrderedIdValueType;
|
||||
using cpputils::value_type::QuantityValueType;
|
||||
using cpputils::value_type::FlagsValueType;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -22,10 +23,15 @@ struct MyQuantityValueType : QuantityValueType<MyQuantityValueType, int64_t> {
|
||||
constexpr explicit MyQuantityValueType(int64_t val): QuantityValueType(val) {}
|
||||
};
|
||||
|
||||
struct MyFlagsValueType : FlagsValueType<MyFlagsValueType, int64_t> {
|
||||
constexpr explicit MyFlagsValueType(int64_t val): FlagsValueType(val) {}
|
||||
};
|
||||
|
||||
}
|
||||
DEFINE_HASH_FOR_VALUE_TYPE(MyIdValueType);
|
||||
DEFINE_HASH_FOR_VALUE_TYPE(MyOrderedIdValueType);
|
||||
DEFINE_HASH_FOR_VALUE_TYPE(MyQuantityValueType);
|
||||
DEFINE_HASH_FOR_VALUE_TYPE(MyFlagsValueType);
|
||||
namespace {
|
||||
|
||||
/**
|
||||
@ -57,6 +63,7 @@ struct IdValueTypeTest_constexpr_test {
|
||||
static_assert(IdValueTypeTest_constexpr_test<MyIdValueType>::success, "");
|
||||
static_assert(IdValueTypeTest_constexpr_test<MyOrderedIdValueType>::success, "");
|
||||
static_assert(IdValueTypeTest_constexpr_test<MyQuantityValueType>::success, "");
|
||||
static_assert(IdValueTypeTest_constexpr_test<MyFlagsValueType>::success, "");
|
||||
|
||||
namespace IdValueTypeTest_constexpr_test_extras {
|
||||
// For some reason, MSVC crashes when these are part of IdValueTypeTest_constexpr_test.
|
||||
@ -67,12 +74,14 @@ namespace IdValueTypeTest_constexpr_test_extras {
|
||||
static_assert(MyOrderedIdValueType(5) != MyOrderedIdValueType(6), "");
|
||||
static_assert(!(MyQuantityValueType(5) == MyQuantityValueType(6)), "");
|
||||
static_assert(MyQuantityValueType(5) != MyQuantityValueType(6), "");
|
||||
static_assert(!(MyFlagsValueType(5) == MyFlagsValueType(6)), "");
|
||||
static_assert(MyFlagsValueType(5) != MyFlagsValueType(6), "");
|
||||
}
|
||||
|
||||
|
||||
template<class Type> class IdValueTypeTest : public testing::Test {
|
||||
};
|
||||
using IdValueTypeTest_types = testing::Types<MyIdValueType, MyOrderedIdValueType, MyQuantityValueType>;
|
||||
using IdValueTypeTest_types = testing::Types<MyIdValueType, MyOrderedIdValueType, MyQuantityValueType, MyFlagsValueType>;
|
||||
TYPED_TEST_CASE(IdValueTypeTest, IdValueTypeTest_types);
|
||||
|
||||
|
||||
@ -397,4 +406,70 @@ TYPED_TEST(QuantityValueTypeTest, ModValue) {
|
||||
EXPECT_EQ(1, TypeParam(7) % TypeParam(3));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tests for FlagsValueType
|
||||
*/
|
||||
|
||||
namespace FlagsValueTypeTest_constexpr_test {
|
||||
static_assert(~MyFlagsValueType(3) != MyFlagsValueType(3), "");
|
||||
static_assert(~~MyFlagsValueType(3) == MyFlagsValueType(3), "");
|
||||
static_assert(~MyFlagsValueType(3) == MyFlagsValueType(~3), "");
|
||||
|
||||
static_assert((MyFlagsValueType(3) & MyFlagsValueType(5)) == MyFlagsValueType(3 & 5), "");
|
||||
static_assert((MyFlagsValueType(3) | MyFlagsValueType(5)) == MyFlagsValueType(3 | 5), "");
|
||||
static_assert((MyFlagsValueType(3) ^ MyFlagsValueType(5)) == MyFlagsValueType(3 ^ 5), "");
|
||||
|
||||
static_assert((MyFlagsValueType(3) &= MyFlagsValueType(5)) == MyFlagsValueType(3 & 5), "");
|
||||
static_assert((MyFlagsValueType(3) |= MyFlagsValueType(5)) == MyFlagsValueType(3 | 5), "");
|
||||
static_assert((MyFlagsValueType(3) ^= MyFlagsValueType(5)) == MyFlagsValueType(3 ^ 5), "");
|
||||
}
|
||||
|
||||
|
||||
template<class Type> class FlagsValueTypeTest : public testing::Test {};
|
||||
using FlagsValueType_types = testing::Types<MyFlagsValueType>;
|
||||
TYPED_TEST_CASE(FlagsValueTypeTest, FlagsValueType_types);
|
||||
|
||||
TYPED_TEST(FlagsValueTypeTest, Invert) {
|
||||
TypeParam a(3);
|
||||
TypeParam b(~3);
|
||||
EXPECT_EQ(b, ~a);
|
||||
|
||||
a = ~a;
|
||||
EXPECT_EQ(b, a);
|
||||
}
|
||||
|
||||
TYPED_TEST(FlagsValueTypeTest, And) {
|
||||
TypeParam a(3);
|
||||
TypeParam b(5);
|
||||
TypeParam c(3 & 5);
|
||||
EXPECT_EQ(c, a & b);
|
||||
|
||||
EXPECT_EQ(c, b &= a);
|
||||
EXPECT_EQ(c, b);
|
||||
}
|
||||
|
||||
TYPED_TEST(FlagsValueTypeTest, Or) {
|
||||
TypeParam a(3);
|
||||
TypeParam b(5);
|
||||
TypeParam c(3 | 5);
|
||||
EXPECT_EQ(c, a | b);
|
||||
|
||||
EXPECT_EQ(c, b |= a);
|
||||
EXPECT_EQ(c, b);
|
||||
}
|
||||
|
||||
TYPED_TEST(FlagsValueTypeTest, Xor) {
|
||||
TypeParam a(3);
|
||||
TypeParam b(5);
|
||||
TypeParam c(3 ^ 5);
|
||||
EXPECT_EQ(c, a ^ b);
|
||||
|
||||
EXPECT_EQ(c, b ^= a);
|
||||
EXPECT_EQ(c, b);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user