From ac63b5af8551ad634c6fdba333ce2b5fc243b29c Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Fri, 14 Sep 2018 01:31:38 -0700 Subject: [PATCH] Add FlagsValueType --- src/cpp-utils/value_type/ValueType.h | 49 +++++++++++++ src/fspp/fs_interface/Dir.h | 1 + test/cpp-utils/value_type/ValueTypeTest.cpp | 77 ++++++++++++++++++++- 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/src/cpp-utils/value_type/ValueType.h b/src/cpp-utils/value_type/ValueType.h index ec6b80a5..640ea05e 100644 --- a/src/cpp-utils/value_type/ValueType.h +++ b/src/cpp-utils/value_type/ValueType.h @@ -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 IdValueType { @@ -209,6 +218,46 @@ private: } }; + +template +class FlagsValueType : public IdValueType { +protected: + using IdValueType::IdValueType; + +public: + + constexpr ConcreteType& operator&=(ConcreteType rhs) noexcept(noexcept(*std::declval() &= std::declval())) { + this->value_ &= rhs.value_; + return *static_cast(this); + } + + constexpr ConcreteType& operator|=(ConcreteType rhs) noexcept(noexcept(*std::declval() |= std::declval())) { + this->value_ |= rhs.value_; + return *static_cast(this); + } + + constexpr ConcreteType& operator^=(ConcreteType rhs) noexcept(noexcept(*std::declval() ^= std::declval())) { + this->value_ ^= rhs.value_; + return *static_cast(this); + } + + constexpr ConcreteType operator~() noexcept(noexcept(~*std::declval())) { + return ConcreteType(~this->value_); + } + + friend constexpr ConcreteType operator&(ConcreteType lhs, ConcreteType rhs) noexcept(noexcept(std::declval() &= std::declval())) { + return lhs &= rhs; + } + + friend constexpr ConcreteType operator|(ConcreteType lhs, ConcreteType rhs) noexcept(noexcept(std::declval() |= std::declval())) { + return lhs |= rhs; + } + + friend constexpr ConcreteType operator^(ConcreteType lhs, ConcreteType rhs) noexcept(noexcept(std::declval() ^= std::declval())) { + return lhs ^= rhs; + } +}; + } } diff --git a/src/fspp/fs_interface/Dir.h b/src/fspp/fs_interface/Dir.h index eac05acb..2706f257 100644 --- a/src/fspp/fs_interface/Dir.h +++ b/src/fspp/fs_interface/Dir.h @@ -3,6 +3,7 @@ #define MESSMER_FSPP_FSINTERFACE_DIR_H_ #include +#include #include #include diff --git a/test/cpp-utils/value_type/ValueTypeTest.cpp b/test/cpp-utils/value_type/ValueTypeTest.cpp index 2f7ab65f..54d0cd82 100644 --- a/test/cpp-utils/value_type/ValueTypeTest.cpp +++ b/test/cpp-utils/value_type/ValueTypeTest.cpp @@ -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 { constexpr explicit MyQuantityValueType(int64_t val): QuantityValueType(val) {} }; +struct MyFlagsValueType : FlagsValueType { + 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::success, ""); static_assert(IdValueTypeTest_constexpr_test::success, ""); static_assert(IdValueTypeTest_constexpr_test::success, ""); +static_assert(IdValueTypeTest_constexpr_test::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 IdValueTypeTest : public testing::Test { }; -using IdValueTypeTest_types = testing::Types; +using IdValueTypeTest_types = testing::Types; 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 FlagsValueTypeTest : public testing::Test {}; +using FlagsValueType_types = testing::Types; +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); +} + }