From df2f1d7a2f9b7143010a49d98dba0ed99b52c759 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Tue, 22 May 2018 00:04:00 -0700 Subject: [PATCH] Start implementing ValueType --- src/cpp-utils/CMakeLists.txt | 1 + src/cpp-utils/value_type/ConfigBuilder.cpp | 1 + src/cpp-utils/value_type/ConfigBuilder.h | 61 ++++++++++++++++ src/cpp-utils/value_type/ValueType.cpp | 5 +- src/cpp-utils/value_type/ValueType.h | 79 +++++++++++---------- test/cpp-utils/value_type/ValueTypeTest.cpp | 58 ++++++++++----- 6 files changed, 143 insertions(+), 62 deletions(-) create mode 100644 src/cpp-utils/value_type/ConfigBuilder.cpp create mode 100644 src/cpp-utils/value_type/ConfigBuilder.h diff --git a/src/cpp-utils/CMakeLists.txt b/src/cpp-utils/CMakeLists.txt index c1f388a1..db4b168d 100644 --- a/src/cpp-utils/CMakeLists.txt +++ b/src/cpp-utils/CMakeLists.txt @@ -48,6 +48,7 @@ set(SOURCES system/time.cpp system/diskspace.cpp value_type/ValueType.cpp + value_type/ConfigBuilder.cpp ) add_library(${PROJECT_NAME} STATIC ${SOURCES}) diff --git a/src/cpp-utils/value_type/ConfigBuilder.cpp b/src/cpp-utils/value_type/ConfigBuilder.cpp new file mode 100644 index 00000000..d538c561 --- /dev/null +++ b/src/cpp-utils/value_type/ConfigBuilder.cpp @@ -0,0 +1 @@ +#include "ConfigBuilder.h" diff --git a/src/cpp-utils/value_type/ConfigBuilder.h b/src/cpp-utils/value_type/ConfigBuilder.h new file mode 100644 index 00000000..d14f358f --- /dev/null +++ b/src/cpp-utils/value_type/ConfigBuilder.h @@ -0,0 +1,61 @@ +#pragma once +#ifndef MESSMER_CPPUTILS_VALUETYPE_CONFIGBUILDER_H_ +#define MESSMER_CPPUTILS_VALUETYPE_CONFIGBUILDER_H_ + +namespace cpputils { + +template class ValueType; + +template +struct ValueTypeConfig final { +private: + /* + * Accessors for building the ValueType class + */ + friend class ValueType; + + using underlying_type = underlyingType; + static constexpr bool value_access_enabled() { return valueAccessEnabled; } + static constexpr bool explicit_value_constructor_enabled() { return explicitValueConstructorEnabled; } + static constexpr bool increment_and_decrement_enabled() { return incrementAndDecrementEnabled; } + + +public: + /* + * Setters for builder pattern + */ + constexpr ValueTypeConfig + enable_value_access() { + static_assert(!valueAccessEnabled, "Can't call enable_value_access() twice"); + return {}; + } + + constexpr ValueTypeConfig + enable_explicit_value_constructor() { + static_assert(!explicitValueConstructorEnabled, "Can't call enable_explicit_value_constructor() twice"); + return {}; + } + + constexpr ValueTypeConfig + enable_increment_and_decrement_operators() { + static_assert(!incrementAndDecrementEnabled, "Can't call enable_increment_and_decrement_operators twice"); + return {}; + }; + + using type = ValueType; + +private: + constexpr ValueTypeConfig() {/* not meant for instantiation*/} +}; + +/** + * Start building a value type. + * tag: Some unique type to make sure the resulting value type is unique + * underlyingType: The type of the underlying values + */ +template +inline constexpr ValueTypeConfig valueType() { return {}; } + +} + +#endif diff --git a/src/cpp-utils/value_type/ValueType.cpp b/src/cpp-utils/value_type/ValueType.cpp index fa166d0f..d0062732 100644 --- a/src/cpp-utils/value_type/ValueType.cpp +++ b/src/cpp-utils/value_type/ValueType.cpp @@ -1,4 +1 @@ -// -// Created by heinzi on 21/05/18. -// - +#include "ValueType.h" diff --git a/src/cpp-utils/value_type/ValueType.h b/src/cpp-utils/value_type/ValueType.h index 74e6e2b3..3644c177 100644 --- a/src/cpp-utils/value_type/ValueType.h +++ b/src/cpp-utils/value_type/ValueType.h @@ -1,29 +1,59 @@ #pragma once -#ifndef MESSMER_CPPUTILS_VALUETYPE_H_ -#define MESSMER_CPPUTILS_VALUETYPE_H_ +#ifndef MESSMER_CPPUTILS_VALUETYPE_VALUETYPE_H_ +#define MESSMER_CPPUTILS_VALUETYPE_VALUETYPE_H_ #include #include namespace cpputils { +namespace details { +// The Helper type is to allow the enable_if to depend on another type, say a local template type of the method. +// If enable_if depended only on class template parameters, it wouldn't work because they're already deduced when deducing the method. +template +using enable_if_t = std::enable_if_t::value && Condition, Type>; +} + // TODO Test template class ValueType final { public: using underlying_type = typename Config::underlying_type; - constexpr explicit ValueType(underlying_type value); + template + constexpr explicit ValueType(details::enable_if_t value) + : _value(value) {} - template - constexpr std::enable_if_t value() const { + template + constexpr details::enable_if_t value() const { return _value; - }; + } - constexpr ValueType& operator++(); - constexpr ValueType operator++(int); - constexpr ValueType& operator--(); - constexpr ValueType operator--(int); + template + constexpr details::enable_if_t operator++() { + ++_value; + return *this; + } + + template + constexpr details::enable_if_t operator++(int) { + ValueType tmp = *this; + ++(*this); + return tmp; + } + + template + constexpr details::enable_if_t operator--() { + --_value; + return *this; + } + + template + constexpr details::enable_if_t operator--(int) { + ValueType tmp = *this; + --(*this); + return tmp; + } constexpr ValueType& operator+=(ValueType rhs); constexpr ValueType& operator-=(ValueType rhs); @@ -65,35 +95,6 @@ inline constexpr ValueType operator "" _bytes(unsigned long long int val 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) { diff --git a/test/cpp-utils/value_type/ValueTypeTest.cpp b/test/cpp-utils/value_type/ValueTypeTest.cpp index a307e207..5ca60550 100644 --- a/test/cpp-utils/value_type/ValueTypeTest.cpp +++ b/test/cpp-utils/value_type/ValueTypeTest.cpp @@ -1,30 +1,50 @@ #include +#include #include +#include -using cpputils::ValueType; +using cpputils::valueType; -class AllEnabledConfig final { - using underlying_type = int; - static constexpr bool allow_value_access() { return true; } -}; +struct Tag1{}; +using AllEnabledValueType = decltype(valueType() + .enable_explicit_value_constructor() + .enable_value_access() +)::type; -using AllEnabledValueType = ValueType; + +/* + * Test value() access + */ 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"); +template struct has_value_access().value())>> : std::true_type { + using actual_result_type = std::result_of_t)(T*)>; + 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 Tag2{}; +using ValueTypeWithValueAccess = decltype(valueType() + .enable_explicit_value_constructor() + .enable_value_access() +)::type; +struct Tag3{}; +using ValueTypeWithoutValueAccess = decltype(valueType() + .enable_explicit_value_constructor() +)::type; -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, ""); -static_assert(has_value_access>::value, ""); -static_assert(has_value_access>::value, ""); -static_assert(!has_value_access>::value, ""); \ No newline at end of file +TEST(ValueTypeTest, valueAccess){ + EXPECT_EQ(3, AllEnabledValueType(3).value()); + EXPECT_EQ(5.5, ValueTypeWithValueAccess(5.5).value()); +} + +struct Tag4{}; +using ValueTypeWithIncrementAndDecrement = decltype(valueType() + .enable_explicit_value_constructor() + .enable_value_access() + .enable_increment_and_decrement_operators() +)::type; +// TODO Test incrementAndDecrement \ No newline at end of file