diff --git a/include/etl/type_def.h b/include/etl/type_def.h index cdd916e7..2671e482 100644 --- a/include/etl/type_def.h +++ b/include/etl/type_def.h @@ -32,10 +32,12 @@ SOFTWARE. #define ETL_TYPE_DEF_INCLUDED #include "platform.h" +#include "type_traits.h" namespace etl { #define ETL_TYPEDEF(T, name) class name##_tag; typedef etl::type_def name + #define ETL_USING(name, T) class name##_tag; typedef etl::type_def name //************************************************************************* /// A template type to define strong typedefs. @@ -43,10 +45,12 @@ namespace etl ///\code /// // Short form. /// ETL_TYPEDEF(int, mytype); + /// or + /// ETL_USING(mytype, int); /// /// // Long form. /// class mytype_t_tag; - /// typedef etl::type_def mytype_t_tag; + /// typedef etl::type_def mytype; ///\endcode //************************************************************************* template @@ -54,16 +58,19 @@ namespace etl { public: + typedef TValue type; typedef TValue value_type; typedef TIdType id_type; //********************************************************************* -#if ETL_USING_CPP11 - ETL_CONSTEXPR type_def() = default; -#endif + ETL_CONSTEXPR type_def() + : value(TValue()) + { + } //********************************************************************* - ETL_CONSTEXPR type_def(TValue value_) + template ::value, void>::type> + ETL_CONSTEXPR type_def(T value_) : value(value_) { } @@ -110,21 +117,28 @@ namespace etl } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator +=(TValue rhs) + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, type_def&>::type + operator +=(T rhs) { value += rhs; return *this; } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator +=(const type_def& rhs) + ETL_CONSTEXPR14 + type_def& operator +=(const type_def& rhs) { value += rhs.value; return *this; } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator -=(TValue rhs) + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, type_def&>::type + operator -=(T rhs) { value -= rhs; return *this; @@ -138,7 +152,10 @@ namespace etl } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator *=(TValue rhs) + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, type_def&>::type + operator *=(T rhs) { value *= rhs; return *this; @@ -152,7 +169,10 @@ namespace etl } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator /=(TValue rhs) + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, type_def&>::type + operator /=(T rhs) { value /= rhs; return *this; @@ -166,7 +186,10 @@ namespace etl } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator %=(TValue rhs) + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, type_def&>::type + operator %=(T rhs) { value %= rhs; return *this; @@ -180,7 +203,10 @@ namespace etl } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator &=(TValue rhs) + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, type_def&>::type + operator &=(T rhs) { value &= rhs; return *this; @@ -194,7 +220,10 @@ namespace etl } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator |=(TValue rhs) + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, type_def&>::type + operator |=(T rhs) { value |= rhs; return *this; @@ -208,7 +237,10 @@ namespace etl } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator ^=(TValue rhs) + template + ETL_CONSTEXPR14 + typename etl::enable_if::value, type_def&>::type + operator ^=(T rhs) { value ^= rhs; return *this; @@ -222,26 +254,19 @@ namespace etl } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator <<=(TValue rhs) + ETL_CONSTEXPR14 type_def& operator <<=(int rhs) { value <<= rhs; return *this; } //********************************************************************* - ETL_CONSTEXPR14 type_def& operator >>=(TValue rhs) + ETL_CONSTEXPR14 type_def& operator >>=(int rhs) { value >>= rhs; return *this; } - //********************************************************************* - ETL_CONSTEXPR14 type_def& operator =(TValue rhs) - { - value = rhs; - return *this; - } - //********************************************************************* #if ETL_USING_CPP11 ETL_CONSTEXPR14 type_def& operator =(const type_def& rhs) = default; @@ -259,24 +284,378 @@ namespace etl return value; } + //********************************************************************* + // + operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator +(const type_def& lhs, T rhs) + { + return type_def(lhs.value + rhs); + } + + //********************************************************************* + template + friend ETL_CONSTEXPR type_def operator +(T lhs, const type_def& rhs) + { + return type_def(lhs + rhs.value); + } + + //********************************************************************* + friend ETL_CONSTEXPR type_def operator +(const type_def& lhs, const type_def& rhs) + { + return type_def(lhs.value + rhs.value); + } + + //********************************************************************* + // - operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator -(const type_def& lhs, T rhs) + { + return type_def(lhs.value - rhs); + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator -(T lhs, const type_def& rhs) + { + return type_def(lhs - rhs.value); + } + + //********************************************************************* + friend ETL_CONSTEXPR type_def operator -(const type_def& lhs, const type_def& rhs) + { + return type_def(lhs.value - rhs.value); + } + + //********************************************************************* + // * operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator *(const type_def& lhs, T rhs) + { + return type_def(lhs.value * rhs); + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator *(T lhs, const type_def& rhs) + { + return type_def(lhs * rhs.value); + } + + //********************************************************************* + friend ETL_CONSTEXPR type_def operator *(const type_def& lhs, const type_def& rhs) + { + return type_def(lhs.value * rhs.value); + } + + //********************************************************************* + // / operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator /(const type_def& lhs, T rhs) + { + return type_def(lhs.value / rhs); + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator /(T lhs, const type_def& rhs) + { + return type_def(lhs / rhs.value); + } + + //********************************************************************* + friend ETL_CONSTEXPR type_def operator /(const type_def& lhs, const type_def& rhs) + { + return type_def(lhs.value / rhs.value); + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator %(const type_def& lhs, T rhs) + { + return type_def(lhs.value % rhs); + } + + //********************************************************************* + // % operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator %(T lhs, const type_def& rhs) + { + return type_def(lhs % rhs.value); + } + + //********************************************************************* + friend ETL_CONSTEXPR type_def operator %(const type_def& lhs, const type_def& rhs) + { + return type_def(lhs.value % rhs.value); + } + + //********************************************************************* + // & operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator &(const type_def& lhs, T rhs) + { + return type_def(lhs.value & rhs); + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator &(T lhs, const type_def& rhs) + { + return type_def(lhs & rhs.value); + } + + //********************************************************************* + friend ETL_CONSTEXPR type_def operator &(const type_def& lhs, const type_def& rhs) + { + return type_def(lhs.value & rhs.value); + } + + //********************************************************************* + // | operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator |(const type_def& lhs, T rhs) + { + return type_def(lhs.value | rhs); + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator |(T lhs, const type_def& rhs) + { + return type_def(lhs | rhs.value); + } + + //********************************************************************* + friend ETL_CONSTEXPR type_def operator |(const type_def& lhs, const type_def& rhs) + { + return type_def(lhs.value | rhs.value); + } + + //********************************************************************* + // ^ operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator ^(const type_def& lhs, T rhs) + { + return type_def(lhs.value ^ rhs); + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, type_def>::type + operator ^(T lhs, const type_def& rhs) + { + return type_def(lhs ^ rhs.value); + } + + //********************************************************************* + friend ETL_CONSTEXPR type_def operator ^(const type_def& lhs, const type_def& rhs) + { + return type_def(lhs.value ^ rhs.value); + } + + //********************************************************************* + // << operator + //********************************************************************* + friend ETL_CONSTEXPR type_def operator <<(const type_def& lhs, int rhs) + { + return type_def(lhs.value << rhs); + } + + //********************************************************************* + // >> operator + //********************************************************************* + friend ETL_CONSTEXPR type_def operator >>(const type_def& lhs, int rhs) + { + return type_def(lhs.value >> rhs); + } + + //********************************************************************* + // < operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator <(const type_def& lhs, T rhs) + { + return lhs.value < rhs; + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator <(T lhs, const type_def& rhs) + { + return lhs < rhs.value; + } + + //********************************************************************* + friend ETL_CONSTEXPR bool operator <(const type_def& lhs, const type_def& rhs) + { + return lhs.value < rhs.value; + } + + //********************************************************************* + // <= operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator <=(const type_def& lhs, T rhs) + { + return lhs.value <= rhs; + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator <=(T lhs, const type_def& rhs) + { + return lhs <= rhs.value; + } + + //********************************************************************* + friend ETL_CONSTEXPR bool operator <=(const type_def& lhs, const type_def& rhs) + { + return lhs.value <= rhs.value; + } + + //********************************************************************* + // > operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator >(const type_def& lhs, T rhs) + { + return lhs.value > rhs; + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator >(T lhs, const type_def& rhs) + { + return lhs > rhs.value; + } + //********************************************************************* friend ETL_CONSTEXPR bool operator >(const type_def& lhs, const type_def& rhs) { return lhs.value > rhs.value; } + //********************************************************************* + // >= operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator >=(const type_def& lhs, T rhs) + { + return lhs.value >= rhs; + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator >=(T lhs, const type_def& rhs) + { + return lhs >= rhs.value; + } + //********************************************************************* friend ETL_CONSTEXPR bool operator >=(const type_def& lhs, const type_def& rhs) { return lhs.value >= rhs.value; } + //********************************************************************* + // == operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator ==(const type_def& lhs, T rhs) + { + return lhs.value == rhs; + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator ==(T lhs, const type_def& rhs) + { + return lhs == rhs.value; + } + //********************************************************************* friend ETL_CONSTEXPR bool operator ==(const type_def& lhs, const type_def& rhs) { return lhs.value == rhs.value; } + //********************************************************************* + // != operator + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator !=(const type_def& lhs, T rhs) + { + return lhs.value != rhs; + } + + //********************************************************************* + template + friend ETL_CONSTEXPR + typename etl::enable_if::value, bool>::type + operator !=(T lhs, const type_def& rhs) + { + return lhs != rhs.value; + } + //********************************************************************* friend ETL_CONSTEXPR bool operator !=(const type_def& lhs, const type_def& rhs) { diff --git a/test/test_type_def.cpp b/test/test_type_def.cpp index f42b593b..30d27772 100644 --- a/test/test_type_def.cpp +++ b/test/test_type_def.cpp @@ -32,20 +32,37 @@ SOFTWARE. #include "etl/type_def.h" -#include "etl/type_traits.h" - namespace { + const char One = 1; + const char Two = 2; + SUITE(test_type_def) { //************************************************************************* - TEST(test_macro) + TEST(test_macro_ETL_TYPEDEF) { ETL_TYPEDEF(uint32_t, type1_t); ETL_TYPEDEF(uint32_t, type2_t); - type1_t t1 = type1_t(1); - type2_t t2 = type2_t(1); + type1_t t1 = type1_t(One); + type2_t t2 = type2_t(One); + + uint32_t i1 = t1.get(); + uint32_t i2 = t2.get(); + + CHECK_EQUAL(i1, i2); + CHECK_TRUE(std::is_trivially_copyable::value); + } + + //************************************************************************* + TEST(test_macro_ETL_USING) + { + ETL_USING(type1_t, uint32_t); + ETL_USING(type2_t, uint32_t); + + type1_t t1 = type1_t(One); + type2_t t2 = type2_t(One); uint32_t i1 = t1.get(); uint32_t i2 = t2.get(); @@ -60,8 +77,8 @@ namespace ETL_TYPEDEF(uint32_t, type1_t); ETL_TYPEDEF(uint32_t, type2_t); - constexpr type1_t t1 = type1_t(1); - constexpr type2_t t2 = type2_t(1); + constexpr type1_t t1 = type1_t(One); + constexpr type2_t t2 = type2_t(One); uint32_t i1 = t1.get(); uint32_t i2 = t2.get(); @@ -78,8 +95,8 @@ namespace class type2_t_tag; typedef etl::type_def type2_t; - type1_t t1 = type1_t(1); - type2_t t2 = type2_t(1); + type1_t t1 = type1_t(One); + type2_t t2 = type2_t(One); uint32_t i1 = t1.get(); uint32_t i2 = t2.get(); @@ -96,8 +113,8 @@ namespace class type2_t_tag; typedef etl::type_def type2_t; - constexpr type1_t t1 = type1_t(1); - constexpr type2_t t2 = type2_t(1); + constexpr type1_t t1 = type1_t(One); + constexpr type2_t t2 = type2_t(One); uint32_t i1 = t1.get(); uint32_t i2 = t2.get(); @@ -114,8 +131,8 @@ namespace class type2_t_tag; typedef etl::type_def type2_t; - type1_t t1(1); - type2_t t2(1); + type1_t t1(One); + type2_t t2(One); CHECK_EQUAL(t1.get(), t2.get()); } @@ -129,14 +146,14 @@ namespace class type2_t_tag; typedef etl::type_def type2_t; - constexpr type1_t t1(1); - constexpr type2_t t2(1); + constexpr type1_t t1(One); + constexpr type2_t t2(One); CHECK_EQUAL(t1.get(), t2.get()); } //************************************************************************* - TEST(test_operators) + TEST(test_unary_operators) { class __type_t__; typedef etl::type_def<__type_t__, uint32_t> type_t; @@ -148,14 +165,14 @@ namespace CHECK_EQUAL(i++, uint32_t(t++)); CHECK_EQUAL(--i, uint32_t(--t)); CHECK_EQUAL(i--, uint32_t(t--)); - CHECK_EQUAL(i += 2, uint32_t(t += 2)); - CHECK_EQUAL(i += 2, uint32_t(t += type_t(2))); - CHECK_EQUAL(i -= 2, uint32_t(t -= 2)); - CHECK_EQUAL(i -= 2, uint32_t(t -= type_t(2))); - CHECK_EQUAL(i *= 2, uint32_t(t *= 2)); - CHECK_EQUAL(i *= 2, uint32_t(t *= type_t(2))); - CHECK_EQUAL(i /= 2, uint32_t(t /= 2)); - CHECK_EQUAL(i /= 2, uint32_t(t /= type_t(2))); + CHECK_EQUAL(i += Two, uint32_t(t += Two)); + CHECK_EQUAL(i += Two, uint32_t(t += type_t(Two))); + CHECK_EQUAL(i -= Two, uint32_t(t -= Two)); + CHECK_EQUAL(i -= Two, uint32_t(t -= type_t(Two))); + CHECK_EQUAL(i *= Two, uint32_t(t *= Two)); + CHECK_EQUAL(i *= Two, uint32_t(t *= type_t(Two))); + CHECK_EQUAL(i /= Two, uint32_t(t /= Two)); + CHECK_EQUAL(i /= Two, uint32_t(t /= type_t(Two))); CHECK_EQUAL(i &= 0xFF00U, uint32_t(t &= 0xFF00U)); CHECK_EQUAL(i &= 0xFF00U, uint32_t(t &= type_t(0xFF00U))); CHECK_EQUAL(i |= 0x003DU, uint32_t(t |= 0x003DU)); @@ -170,6 +187,52 @@ namespace CHECK_EQUAL(0x1234U, uint32_t(t)); } + //************************************************************************* + TEST(test_binary_operators) + { + class __type_t__; + using type_t = etl::type_def<__type_t__, uint32_t> ; + + uint32_t i1 = 0x5A3DUL; + uint32_t i2 = 0xB47AUL; + type_t t1(0x5A3DUL); + type_t t2(0xB47AUL); + + CHECK_EQUAL(i1 + Two, t1 + Two); + CHECK_EQUAL(Two + i1, Two + t1); + CHECK_EQUAL(i1 + i2, t1 + t2); + + CHECK_EQUAL(i1 - Two, t1 - Two); + CHECK_EQUAL(i2 - i1, i2 - t1); + CHECK_EQUAL(i2 - i1, t2 - t1); + + CHECK_EQUAL(i1 * Two, t1 * Two); + CHECK_EQUAL(Two * i1, Two * t1); + CHECK_EQUAL(i1 * i2, t1 * t2); + + CHECK_EQUAL(i1 / Two, t1 / Two); + CHECK_EQUAL(i2 / i1, i2 / t1); + CHECK_EQUAL(i2 / i1, t2 / t1); + + CHECK_EQUAL(uint32_t(0xFF00) & i1, uint32_t(0xFF00) & t1); + CHECK_EQUAL(i1 & uint32_t(0xFF00), t1 & uint32_t(0xFF00)); + CHECK_EQUAL(uint32_t(0xFF00) & i1, type_t(0xFF00UL) & t1); + + CHECK_EQUAL(uint32_t(0x003D) | i1, uint32_t(0x003D) | t1); + CHECK_EQUAL(i1 | uint32_t(0x003D), t1 | uint32_t(0x003D)); + CHECK_EQUAL(uint32_t(0x003D) | i1, type_t(0x003DUL) | t1); + + CHECK_EQUAL(uint32_t(0xAA55) ^ i1, uint32_t(0xAA55) ^ t1); + CHECK_EQUAL(i1 ^ uint32_t(0xAA55), t1 ^ uint32_t(0xAA55)); + CHECK_EQUAL(uint32_t(0xAA55) ^ i1, type_t(0xAA55UL) ^ t1); + + CHECK_EQUAL(i1 << 2, t1 << 2); + CHECK_EQUAL(i1 >> 2, t1 >> 2); + + CHECK_EQUAL(i1 % uint32_t(23), t1 % uint32_t(23)); + CHECK_EQUAL(uint32_t(23) % i1, uint32_t(23) % t1); + } + //************************************************************************* TEST(test_comparisons) { @@ -177,7 +240,7 @@ namespace typedef etl::type_def<__type_t__, uint32_t> type_t; type_t t1(1); - type_t t2(2); + type_t t2(Two); type_t t3(t1); type_t t4(t2); @@ -200,7 +263,7 @@ namespace typedef etl::type_def<__type_t__, uint32_t> type_t; constexpr type_t t1(1); - constexpr type_t t2(2); + constexpr type_t t2(Two); constexpr bool eq = t1 == t1; constexpr bool neq = t1 == t2; diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 433d5c9c..4b378625 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -748,18 +748,17 @@ namespace enum1_t e1 = enum1_t::b2; enum2_t e2 = enum2_t::c0; - CHECK_TRUE(etl::is_same>::value); - CHECK_TRUE(etl::is_same>::value); - CHECK_TRUE(etl::is_same>::value); + CHECK_TRUE((etl::is_same>::value)); + CHECK_TRUE((etl::is_same>::value)); + CHECK_TRUE((etl::is_same>::value)); CHECK_EQUAL(etl::to_underlying(e0), 't'); CHECK_EQUAL(etl::to_underlying(e1), 5); CHECK_EQUAL(etl::to_underlying(e2), -2); - CHECK_EQUAL(etl::to_underlying(e3), 2); CHECK_EQUAL(etl::to_underlying(enum0_t::a0), 'e'); CHECK_EQUAL(etl::to_underlying(enum0_t::a2), 'l'); CHECK_EQUAL(etl::to_underlying(enum0_t::a3), '3'); - CHECK_EQUAL(etl::to_underlying(enum3_t::b1), 3); + CHECK_EQUAL(etl::to_underlying(enum1_t::b1), 3); CHECK_EQUAL(etl::to_underlying(enum2_t::c1), 100); } #endif