From e45994eb49cf9b4f37db47d84efb5aeacae72eb6 Mon Sep 17 00:00:00 2001 From: jwellbelove Date: Mon, 23 Jan 2017 14:17:36 +0000 Subject: [PATCH] Initial experimental implementation of user_type --- src/user_type.h | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/user_type.h diff --git a/src/user_type.h b/src/user_type.h new file mode 100644 index 00000000..06d20c96 --- /dev/null +++ b/src/user_type.h @@ -0,0 +1,132 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +http://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef __ETL_USER_TYPE__ +#define __ETL_USER_TYPE__ + +///\defgroup user_type user_type +/// Smart enumerations.
+/// A method of declaring a user type that also contains a set of constants, +/// but are not constrained to just those values. +/// This contrasts with 'enum_type', where the values are expected to only contain +/// those defined as constants. +/// Declaring the enumeration. +///\code +/// DECLARE_USER_TYPE(CompassDirection, int) +/// USER_TYPE(North, 0) +/// USER_TYPE(South, 180) +/// USER_TYPE(East, 90) +/// USER_TYPE(West, 270) +/// END_USER_TYPE +///\endcode +/// Using the enumeration. +///\code +/// CompassDirection direction; // Default construction. +/// +/// direction = CompassDirection::North; // Assignment from an enumeration constant; +/// +/// int value = int(direction); // Explicit conversion to 'int'. +/// int value = direction.get(); +/// +/// const int& value = direction.get(); // Bind to internal value. +/// +/// direction = CompassDirection(value); // Explicit conversion from 'int'. +/// +/// direction = CompassDirection(3); // Explicit conversion from a value. +/// +/// ++direction; // Manipulate the value; +/// direction -= 20; +/// +/// direction = value; // Implicit conversion from 'int'. **** Compilation error **** +/// +/// std::cout << "Direction = " << direction.c_str(); // Prints "Direction = North" +///\endcode +/// If a conversion to a string is not required then the 'ENUM_TYPE' declaration may be omitted. +/// In that case the c_str() function will return a "?". This will also be the case for any +/// enumeration value that does not have an ENUM_TYPE entry. +///\ingroup utilities + +//***************************************************************************** +// The declaration of the structure. +//***************************************************************************** +#define DECLARE_USER_TYPE(TypeName, ValueType) \ + struct TypeName \ + { \ + enum enum_type \ + { \ + +//***************************************************************************** +// The predefined constants. +//***************************************************************************** +#define USER_TYPE(enum_name, value) \ + enum_name = value, + +//***************************************************************************** +// The final section of the structure. +//***************************************************************************** +#define END_USER_TYPE \ + }; \ + + typedef ValueType value_type; \ + TypeName() {} \ + TypeName(const TypeName &other) : value(other.value) {} \ + TypeName(enum_type value) : value(value) {} \ + TypeName& operator=(const TypeName &other) {value = other.value; return *this;} \ + explicit TypeName(value_type value) : value(static_cast(value)) {} \ + explicit operator value_type() const {return static_cast(value);} \ + value_type& get() {return static_cast(value);} \ + const value_type& get() const {return static_cast(value);} \ + TypeName& operator ++() { ++value; return *this; } \ + TypeName operator ++(int) { TypeName temp(*this); TypeName::operator ++(); return temp; } \ + TypeName& operator --() { --value; return *this; } + TypeName operator --(int) { TypeName temp(*this); TypeName::operator --(); return temp; } \ + TypeName& operator +=(value_type rhs) { value += rhs; return *this; } \ + TypeName& operator +=(const TypeName& rhs) { value += rhs.value; return *this; } \ + TypeName& operator -=(value_type rhs) { value -= rhs; return *this; } \ + TypeName& operator -=(const TypeName& rhs) { value -= rhs.value; return *this; } \ + TypeName& operator *=(value_type rhs) { value *= rhs; return *this; } \ + TypeName& operator *=(const TypeName& rhs) { value *= rhs.value; return *this; } \ + TypeName& operator /=(value_type rhs) { value /= rhs; return *this; } \ + TypeName& operator /=(const TypeName& rhs) { value /= rhs.value; return *this; } \ + TypeName& operator %=(value_type rhs) { value %= rhs; return *this; } \ + TypeName& operator %=(const TypeName& rhs) { value %= rhs.value; return *this; } \ + TypeName& operator &=(value_type rhs) { value &= rhs; return *this; } \ + TypeName& operator &=(const TypeName& rhs) { value &= rhs.value; return *this; } \ + TypeName& operator |=(value_type rhs) { value |= rhs; return *this; } \ + TypeName& operator |=(const TypeName& rhs) { value |= rhs.value; return *this; } \ + TypeName& operator ^=(value_type rhs) { value ^= rhs; return *this; } \ + TypeName& operator ^=(const TypeName& rhs) { value ^= rhs.value; return *this; } \ + TypeName& operator <<=(value_type rhs) { value <<= rhs; return *this; } \ + TypeName& operator >>=(value_type rhs) { value >>= rhs; return *this; } \ +private: \ + value_type value; \ +}; + +#endif