diff --git a/src/cpp-utils/CMakeLists.txt b/src/cpp-utils/CMakeLists.txt index 9a163be9..c1f388a1 100644 --- a/src/cpp-utils/CMakeLists.txt +++ b/src/cpp-utils/CMakeLists.txt @@ -47,6 +47,7 @@ set(SOURCES system/memory_windows.cpp system/time.cpp system/diskspace.cpp + value_type/ValueType.cpp ) add_library(${PROJECT_NAME} STATIC ${SOURCES}) diff --git a/src/cpp-utils/value_type/ValueType.cpp b/src/cpp-utils/value_type/ValueType.cpp new file mode 100644 index 00000000..fa166d0f --- /dev/null +++ b/src/cpp-utils/value_type/ValueType.cpp @@ -0,0 +1,4 @@ +// +// Created by heinzi on 21/05/18. +// + diff --git a/src/cpp-utils/value_type/ValueType.h b/src/cpp-utils/value_type/ValueType.h new file mode 100644 index 00000000..74e6e2b3 --- /dev/null +++ b/src/cpp-utils/value_type/ValueType.h @@ -0,0 +1,211 @@ +#pragma once +#ifndef MESSMER_CPPUTILS_VALUETYPE_H_ +#define MESSMER_CPPUTILS_VALUETYPE_H_ + +#include +#include + +namespace cpputils { + +// TODO Test +template +class ValueType final { +public: + using underlying_type = typename Config::underlying_type; + + constexpr explicit ValueType(underlying_type value); + + template + constexpr std::enable_if_t value() const { + return _value; + }; + + constexpr ValueType& operator++(); + constexpr ValueType operator++(int); + constexpr ValueType& operator--(); + constexpr ValueType operator--(int); + + constexpr ValueType& operator+=(ValueType rhs); + constexpr ValueType& operator-=(ValueType rhs); + constexpr ValueType& operator*=(underlying_type rhs); + constexpr ValueType& operator/=(underlying_type rhs); + constexpr ValueType& operator%=(underlying_type rhs); + +private: + friend struct std::hash; + underlying_type _value; +}; + +/*template +constexpr ValueType operator "" _bytes(unsigned long long int value);*/ + +template constexpr ValueType operator+(ValueType lhs, ValueType rhs); +template constexpr ValueType operator-(ValueType lhs, ValueType rhs); +template constexpr ValueType operator*(ValueType lhs, typename Config::underlying_type rhs); +template constexpr ValueType operator*(typename Config::underlying_type lhs, ValueType rhs); +template constexpr ValueType operator/(ValueType lhs, typename Config::underlying_type rhs); +template constexpr typename Config::underlying_type operator/(ValueType lhs, ValueType rhs); +template constexpr ValueType operator%(ValueType lhs, typename Config::underlying_type rhs); +template constexpr typename Config::underlying_type operator%(ValueType lhs, ValueType rhs); + +template constexpr bool operator==(ValueType lhs, ValueType rhs); +template constexpr bool operator!=(ValueType lhs, ValueType rhs); +template constexpr bool operator<(ValueType lhs, ValueType rhs); +template constexpr bool operator>(ValueType lhs, ValueType rhs); +template constexpr bool operator<=(ValueType lhs, ValueType rhs); +template constexpr bool operator>=(ValueType lhs, ValueType rhs); + + +/* + * Implementation follows + */ + +/*template +inline constexpr ValueType operator "" _bytes(unsigned long long int value) { + return ValueType(value); +}*/ + +template +inline constexpr ValueType::ValueType(typename Config::underlying_type value) + : _value(value) {} + +template +inline constexpr ValueType& ValueType::operator++() { + ++_value; + return *this; +} + +template +inline constexpr ValueType ValueType::operator++(int) { + ValueType tmp = *this; + ++(*this); + return tmp; +} + +template +inline constexpr ValueType& ValueType::operator--() { + --_value; + return *this; +} + +template +inline constexpr ValueType ValueType::operator--(int) { + ValueType tmp = *this; + --(*this); + return tmp; +} + +template +inline constexpr ValueType& ValueType::operator+=(ValueType rhs) { + _value += rhs._value; + return *this; +} + +template +inline constexpr ValueType& ValueType::operator-=(ValueType rhs) { + _value -= rhs._value; + return *this; +} + +template +inline constexpr ValueType& ValueType::operator*=(typename Config::underlying_type rhs) { + _value *= rhs; + return *this; +} + +template +inline constexpr ValueType& ValueType::operator/=(typename Config::underlying_type rhs) { + _value /= rhs; + return *this; +} + +template +inline constexpr ValueType& ValueType::operator%=(typename Config::underlying_type rhs) { + _value %= rhs; + return *this; +} + +template +inline constexpr ValueType operator+(ValueType lhs, ValueType rhs) { + return lhs += rhs; +} + +template +inline constexpr ValueType operator-(ValueType lhs, ValueType rhs) { + return lhs -= rhs; +} + +template +inline constexpr ValueType operator*(ValueType lhs, typename Config::underlying_type rhs) { + return lhs *= rhs; +} + +template +inline constexpr ValueType operator*(typename Config::underlying_type lhs, ValueType rhs) { + return rhs * lhs; +} + +template +inline constexpr ValueType operator/(ValueType lhs, typename Config::underlying_type rhs) { + return lhs /= rhs; +} + +template +inline constexpr typename Config::underlying_type operator/(ValueType lhs, ValueType rhs) { + return lhs.value() / rhs.value(); +} + +template +inline constexpr ValueType operator%(ValueType lhs, typename Config::underlying_type rhs) { + return lhs %= rhs; +} + +template +inline constexpr typename Config::underlying_type operator%(ValueType lhs, ValueType rhs) { + return lhs.value() % rhs.value(); +} + + +template +inline constexpr bool operator==(ValueType lhs, ValueType rhs) { + return lhs.value() == rhs.value(); +} + +template +inline constexpr bool operator!=(ValueType lhs, ValueType rhs) { + return !operator==(lhs, rhs); +} + +template +inline constexpr bool operator<(ValueType lhs, ValueType rhs) { + return lhs.value() < rhs.value(); +} + +template +inline constexpr bool operator>(ValueType lhs, ValueType rhs) { + return lhs.value() > rhs.value(); +} + +template +inline constexpr bool operator<=(ValueType lhs, ValueType rhs) { + return !operator>(lhs, rhs); +} + +template +inline constexpr bool operator>=(ValueType lhs, ValueType rhs) { + return !operator<(lhs, rhs); +} + +} + +namespace std { + template + struct hash> { + constexpr hash() = default; + constexpr size_t operator()(cpputils::ValueType v) { + return v._value; + } + }; +} + +#endif diff --git a/test/cpp-utils/CMakeLists.txt b/test/cpp-utils/CMakeLists.txt index d185504e..1d87df95 100644 --- a/test/cpp-utils/CMakeLists.txt +++ b/test/cpp-utils/CMakeLists.txt @@ -50,6 +50,7 @@ set(SOURCES system/TimeTest.cpp system/MemoryTest.cpp system/HomedirTest.cpp + value_type/ValueTypeTest.cpp ) add_executable(${PROJECT_NAME} ${SOURCES}) diff --git a/test/cpp-utils/value_type/ValueTypeTest.cpp b/test/cpp-utils/value_type/ValueTypeTest.cpp new file mode 100644 index 00000000..a307e207 --- /dev/null +++ b/test/cpp-utils/value_type/ValueTypeTest.cpp @@ -0,0 +1,30 @@ +#include +#include + +using cpputils::ValueType; + +class AllEnabledConfig final { + using underlying_type = int; + static constexpr bool allow_value_access() { return true; } +}; + +using AllEnabledValueType = ValueType; + +template struct has_value_access : std::false_type {}; +template struct has_value_access> : std::true_type { + static_assert(std::is_same>::value, "value() method returns wrong type"); +}; + +struct ConfigWithValueAccess final { + using underlying_type = int; + static constexpr bool allow_value_access() { return true; } +}; + +struct ConfigWithoutValueAccess final { + using underlying_type = int; + static constexpr bool allow_value_access() { return false; } +}; + +static_assert(has_value_access>::value, ""); +static_assert(has_value_access>::value, ""); +static_assert(!has_value_access>::value, ""); \ No newline at end of file