| @@ -1,6 +1,6 @@ | |||
| #pragma once | |||
| #include <cppcore/conversion.h> | |||
| #include <cppcore/define.h> | |||
| #include <cppcore/misc.h> | |||
| #include <cppcore/threading.h> | |||
| #include "cppcore/conversion.h" | |||
| #include "cppcore/define.h" | |||
| #include "cppcore/misc.h" | |||
| #include "cppcore/threading.h" | |||
| @@ -1,6 +1,6 @@ | |||
| #pragma once | |||
| #include <cppcore/conversion/byteorder.h> | |||
| #include <cppcore/conversion/enum.h> | |||
| #include <cppcore/conversion/string.h> | |||
| #include <cppcore/conversion/time.h> | |||
| #include "conversion/byteorder.h" | |||
| #include "conversion/enum.h" | |||
| #include "conversion/string.h" | |||
| #include "conversion/time.h" | |||
| @@ -1,8 +1,8 @@ | |||
| #pragma once | |||
| #include <cppcore/misc/exception.h> | |||
| #include <cppcore/misc/flags.h> | |||
| #include <cppcore/misc/indent.h> | |||
| #include <cppcore/misc/stream.h> | |||
| #include <cppcore/misc/typehelper.h> | |||
| #include <cppcore/misc/utils.h> | |||
| #include "misc/exception.h" | |||
| #include "misc/flags.h" | |||
| #include "misc/indent.h" | |||
| #include "misc/stream.h" | |||
| #include "misc/typehelper.h" | |||
| #include "misc/utils.h" | |||
| @@ -7,64 +7,76 @@ namespace cppcore | |||
| namespace __impl | |||
| { | |||
| constexpr long default_indent = 4; | |||
| inline int indent_stream_index() | |||
| { | |||
| static const int value = std::ios::xalloc(); | |||
| return value; | |||
| } | |||
| /** | |||
| * @brief Returns the index where the indention value is stored inside the stream. | |||
| */ | |||
| inline int indent_stream_index(); | |||
| inline int indent_count_stream_index() | |||
| { | |||
| static const int value = std::ios::xalloc(); | |||
| return value; | |||
| } | |||
| /** | |||
| * @brief Returns the index where the current indention level is stored inside the stream. | |||
| */ | |||
| inline int indent_level_stream_index(); | |||
| /** | |||
| * @brief Helper class to set the stream indention. | |||
| */ | |||
| struct set_indent_impl | |||
| { int value; }; | |||
| } | |||
| inline auto setindent(int value) | |||
| { return __impl::set_indent_impl { value }; } | |||
| /** | |||
| * @brief Set the indention of a stream. | |||
| * | |||
| * @param[in] value New indention value. | |||
| * | |||
| * @return Helper class to set the indention value. | |||
| */ | |||
| inline auto setindent(int value); | |||
| inline std::ostream& incindent(std::ostream& os) | |||
| { | |||
| ++os.iword(__impl::indent_stream_index()); | |||
| return os; | |||
| } | |||
| /** | |||
| * @brief Increment the current indention level by one. | |||
| * | |||
| * @param[in] os Stream to increment the indention level for. | |||
| * | |||
| * @return Stream passed to this function. | |||
| */ | |||
| inline std::ostream& incindent(std::ostream& os); | |||
| inline std::ostream& decindent(std::ostream& os) | |||
| { | |||
| auto& indent = os.iword(__impl::indent_stream_index()); | |||
| if (--indent < 0) | |||
| indent = 0; | |||
| return os; | |||
| } | |||
| /** | |||
| * @brief Decrement the current indention level by one. | |||
| * | |||
| * @param[in] os Stream to decrement the indention level for. | |||
| * | |||
| * @return Stream passed to this function. | |||
| */ | |||
| inline std::ostream& decindent(std::ostream& os); | |||
| inline std::ostream& indent(std::ostream& os) | |||
| { | |||
| auto i = os.iword(__impl::indent_stream_index()); | |||
| auto c = __impl::default_indent + os.iword(__impl::indent_count_stream_index()); | |||
| i *= c; | |||
| if (i >= 0) | |||
| { | |||
| os << std::endl; | |||
| while (i--) | |||
| os.put(' '); | |||
| } | |||
| return os; | |||
| } | |||
| /** | |||
| * @brief Add a line break and indention to the stream. | |||
| * | |||
| * @param[in] os Stream to decrement the indention level for. | |||
| * | |||
| * @return Stream passed to this function. | |||
| */ | |||
| inline std::ostream& indent(std::ostream& os); | |||
| } | |||
| namespace std | |||
| { | |||
| /** | |||
| * @brief Write the helper class to stream using the << operator. | |||
| */ | |||
| template<typename T_char, typename T_traits> | |||
| inline basic_ostream<T_char, T_traits>& operator<< (basic_ostream<T_char, T_traits>& os, const cppcore::__impl::set_indent_impl& i) | |||
| { | |||
| using namespace ::cppcore; | |||
| os.iword(__impl::indent_count_stream_index()) = i.value - __impl::default_indent; | |||
| return os; | |||
| } | |||
| inline basic_ostream<T_char, T_traits>& operator<< ( | |||
| basic_ostream<T_char, T_traits>& os, | |||
| const cppcore::__impl::set_indent_impl& i); | |||
| } | |||
| #include "indent.inl" | |||
| @@ -0,0 +1,69 @@ | |||
| #pragma once | |||
| #include "indent.h" | |||
| namespace cppcore | |||
| { | |||
| namespace __impl | |||
| { | |||
| int indent_stream_index() | |||
| { | |||
| static const int value = std::ios::xalloc(); | |||
| return value; | |||
| } | |||
| int indent_level_stream_index() | |||
| { | |||
| static const int value = std::ios::xalloc(); | |||
| return value; | |||
| } | |||
| } | |||
| auto setindent(int value) | |||
| { return __impl::set_indent_impl { value }; } | |||
| std::ostream& incindent(std::ostream& os) | |||
| { | |||
| ++os.iword(__impl::indent_stream_index()); | |||
| return os; | |||
| } | |||
| std::ostream& decindent(std::ostream& os) | |||
| { | |||
| auto& indent = os.iword(__impl::indent_stream_index()); | |||
| if (--indent < 0) | |||
| indent = 0; | |||
| return os; | |||
| } | |||
| std::ostream& indent(std::ostream& os) | |||
| { | |||
| auto i = os.iword(__impl::indent_stream_index()); | |||
| auto c = __impl::default_indent + os.iword(__impl::indent_level_stream_index()); | |||
| i *= c; | |||
| if (i >= 0) | |||
| { | |||
| os << std::endl; | |||
| while (i--) | |||
| os.put(' '); | |||
| } | |||
| return os; | |||
| } | |||
| } | |||
| namespace std | |||
| { | |||
| template<typename T_char, typename T_traits> | |||
| inline basic_ostream<T_char, T_traits>& operator<< (basic_ostream<T_char, T_traits>& os, const cppcore::__impl::set_indent_impl& i) | |||
| { | |||
| using namespace ::cppcore; | |||
| os.iword(__impl::indent_level_stream_index()) = i.value - __impl::default_indent; | |||
| return os; | |||
| } | |||
| } | |||
| @@ -0,0 +1,262 @@ | |||
| #pragma once | |||
| #include <memory> | |||
| #include "exception.h" | |||
| namespace cppcore | |||
| { | |||
| template<typename T_value> | |||
| struct nullable | |||
| { | |||
| public: | |||
| using value_type = T_value; | |||
| struct value_container | |||
| { | |||
| value_type value; | |||
| template<class... T_args> | |||
| inline value_container(T_args&&... p_args) | |||
| : value(std::forward<T_args>(p_args)...) | |||
| { } | |||
| }; | |||
| using value_container_ptr_u = std::unique_ptr<value_container>; | |||
| private: | |||
| value_container_ptr_u _container; | |||
| public: | |||
| /** | |||
| * @brief Default constructor. | |||
| */ | |||
| inline nullable() = default; | |||
| /** | |||
| * @brief Construtor to create the object. Parameters will passed to the constructor of the value type. | |||
| */ | |||
| template<class... T_args> | |||
| inline nullable(T_args&&... p_args) | |||
| : _container(new value_container(std::forward<T_args>(p_args)...)) | |||
| { } | |||
| /** | |||
| * @brief Copy constructor. | |||
| */ | |||
| inline nullable(nullable& other) | |||
| : _container(other | |||
| ? new value_container(*other) | |||
| : nullptr) | |||
| { } | |||
| /** | |||
| * @brief Copy constructor. | |||
| */ | |||
| inline nullable(const nullable& other) | |||
| : _container(other | |||
| ? new value_container(*other) | |||
| : nullptr) | |||
| { } | |||
| /** | |||
| * @brief Move constructor. | |||
| */ | |||
| inline nullable(nullable&& other) | |||
| : _container(std::move(other)._container) | |||
| { } | |||
| public: | |||
| /** | |||
| * @brief Assignment constructor. | |||
| */ | |||
| inline decltype(auto) operator=(value_type&& t) | |||
| { | |||
| _container.reset(new value_container(std::forward<value_type>(t))); | |||
| return *this; | |||
| } | |||
| /** | |||
| * @brief Copy assignment constructor. | |||
| */ | |||
| inline decltype(auto) operator=(const nullable& other) | |||
| { | |||
| _container.reset(other | |||
| ? new value_container(*other) | |||
| : nullptr); | |||
| return *this; | |||
| } | |||
| /** | |||
| * @brief Move assignment constructor. | |||
| */ | |||
| inline decltype(auto) operator=(nullable&& other) | |||
| { | |||
| _container = std::move(other._container); | |||
| return *this; | |||
| } | |||
| public: | |||
| /** | |||
| * @brief Get the stored value. | |||
| */ | |||
| inline value_type& value() | |||
| { check(); return _container->value; } | |||
| /** | |||
| * @brief Get the stored value. | |||
| */ | |||
| inline const value_type& value() const | |||
| { check(); return _container->value; } | |||
| /** | |||
| * @brief Check if the object has an value assigned. | |||
| */ | |||
| inline bool has_value() const | |||
| { return static_cast<bool>(_container); } | |||
| /** | |||
| * @brief Reset the object. THis will release the stored value. | |||
| */ | |||
| inline void reset() | |||
| { _container.reset(); } | |||
| public: | |||
| /** | |||
| * @brief Operator to access the stored value. | |||
| */ | |||
| inline decltype(auto) operator*() | |||
| { return value(); } | |||
| /** | |||
| * @brief Operator to access the stored value. | |||
| */ | |||
| inline decltype(auto) operator*() const | |||
| { return value(); } | |||
| /** | |||
| * @brief Operator to access the stored value. | |||
| */ | |||
| inline decltype(auto) operator->() | |||
| { return &value(); } | |||
| /** | |||
| * @brief Operator to access the stored value. | |||
| */ | |||
| inline decltype(auto) operator->() const | |||
| { return &value(); } | |||
| /** | |||
| * @brief Operator to access the stored value. | |||
| */ | |||
| inline decltype(auto) operator()() | |||
| { return value(); } | |||
| /** | |||
| * @brief Operator to access the soted value. | |||
| */ | |||
| inline decltype(auto) operator()() const | |||
| { return value(); } | |||
| /** | |||
| * @brief Convert to boolean. | |||
| */ | |||
| inline explicit operator bool() const | |||
| { return has_value(); } | |||
| private: | |||
| /** | |||
| * @brief Check if the object has an value assigned. If not raise an exception. | |||
| */ | |||
| inline void check() const | |||
| { | |||
| if (!has_value()) | |||
| throw invalid_operation_exception("nullable does not have a value"); | |||
| } | |||
| }; | |||
| /* operator== */ | |||
| template<typename T_nullable> | |||
| inline bool operator==(const T_nullable& lhs, const typename T_nullable::value_type& rhs) | |||
| { return lhs.has_value() && *lhs == rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator==(const typename T_nullable::value_type& lhs, const T_nullable& rhs) | |||
| { return rhs.has_value() && lhs == *rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator==(const T_nullable& lhs, const T_nullable& rhs) | |||
| { return lhs.has_value() && rhs.has_value() && *lhs == *rhs; } | |||
| /* operator!= */ | |||
| template<typename T_nullable> | |||
| inline bool operator!=(const T_nullable& lhs, const typename T_nullable::value_type& rhs) | |||
| { return lhs.has_value() && *lhs != rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator!=(const typename T_nullable::value_type& lhs, const T_nullable& rhs) | |||
| { return rhs.has_value() && lhs != *rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator!=(const T_nullable& lhs, const T_nullable& rhs) | |||
| { return lhs.has_value() && rhs.has_value() && *lhs != *rhs; } | |||
| /* operator< */ | |||
| template<typename T_nullable> | |||
| inline bool operator<(const T_nullable& lhs, const typename T_nullable::value_type& rhs) | |||
| { return lhs.has_value() && *lhs < rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator<(const typename T_nullable::value_type& lhs, const T_nullable& rhs) | |||
| { return rhs.has_value() && lhs < *rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator<(const T_nullable& lhs, const T_nullable& rhs) | |||
| { return lhs.has_value() && rhs.has_value() && *lhs < *rhs; } | |||
| /* operator> */ | |||
| template<typename T_nullable> | |||
| inline bool operator>(const T_nullable& lhs, const typename T_nullable::value_type& rhs) | |||
| { return lhs.has_value() && *lhs > rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator>(const typename T_nullable::value_type& lhs, const T_nullable& rhs) | |||
| { return rhs.has_value() && lhs > *rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator>(const T_nullable& lhs, const T_nullable& rhs) | |||
| { return lhs.has_value() && rhs.has_value() && *lhs > *rhs; } | |||
| /* operator<= */ | |||
| template<typename T_nullable> | |||
| inline bool operator<=(const T_nullable& lhs, const typename T_nullable::value_type& rhs) | |||
| { return lhs.has_value() && *lhs <= rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator<=(const typename T_nullable::value_type& lhs, const T_nullable& rhs) | |||
| { return rhs.has_value() && lhs <= *rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator<=(const T_nullable& lhs, const T_nullable& rhs) | |||
| { return lhs.has_value() && rhs.has_value() && *lhs <= *rhs; } | |||
| /* operator>= */ | |||
| template<typename T_nullable> | |||
| inline bool operator>=(const T_nullable& lhs, const typename T_nullable::value_type& rhs) | |||
| { return lhs.has_value() && *lhs >= rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator>=(const typename T_nullable::value_type& lhs, const T_nullable& rhs) | |||
| { return rhs.has_value() && lhs >= *rhs; } | |||
| template<typename T_nullable> | |||
| inline bool operator>=(const T_nullable& lhs, const T_nullable& rhs) | |||
| { return lhs.has_value() && rhs.has_value() && *lhs >= *rhs; } | |||
| } | |||
| @@ -9,7 +9,7 @@ namespace cppcore | |||
| inline size_t bit_count(uint32_t u); | |||
| /** | |||
| * @breif Try to dynamic cast the passed value to the given type. | |||
| * @brief Try to dynamic cast the passed value to the given type. | |||
| * | |||
| * @tparam T Type to cast. | |||
| * @tparam S Type to cast to. | |||
| @@ -1,3 +1,3 @@ | |||
| #pragma once | |||
| #include <cppcore/threading/cancellation_token.h> | |||
| #include "threading/cancellation_token.h" | |||
| @@ -0,0 +1,269 @@ | |||
| #include <gtest/gtest.h> | |||
| #include <cppcore/misc/nullable.h> | |||
| struct TestData | |||
| { | |||
| static int ctorCount; | |||
| static int dtorCount; | |||
| TestData() | |||
| { ++ctorCount; } | |||
| ~TestData() | |||
| { ++dtorCount; } | |||
| }; | |||
| struct NonCopyableTestData | |||
| { | |||
| int value; | |||
| NonCopyableTestData(int v) : | |||
| value(v) | |||
| { } | |||
| NonCopyableTestData(NonCopyableTestData&& other) : | |||
| value(0) | |||
| { std::swap(value, other.value); } | |||
| NonCopyableTestData(const NonCopyableTestData&) = delete; | |||
| }; | |||
| using NullableInt = ::cppcore::nullable<int>; | |||
| using NullableIntRef = ::cppcore::nullable<int&>; | |||
| using NullableString = ::cppcore::nullable<std::string>; | |||
| using NullableTestData = ::cppcore::nullable<TestData>; | |||
| using NullableNonCopyableTestData = ::cppcore::nullable<NonCopyableTestData>; | |||
| int TestData::ctorCount = 0; | |||
| int TestData::dtorCount = 0; | |||
| using namespace ::cppcore; | |||
| using namespace ::testing; | |||
| TEST(nullable_tests, ctor_empty) | |||
| { | |||
| NullableInt n1; | |||
| NullableIntRef n2; | |||
| EXPECT_FALSE(static_cast<bool>(n1)); | |||
| EXPECT_FALSE(static_cast<bool>(n2)); | |||
| } | |||
| TEST(nullable_tests, ctor_value) | |||
| { | |||
| int i = 5; | |||
| NullableInt n1(i); | |||
| NullableIntRef n2(i); | |||
| EXPECT_TRUE(static_cast<bool>(n1)); | |||
| EXPECT_TRUE(static_cast<bool>(n2)); | |||
| EXPECT_EQ (5, n1()); | |||
| EXPECT_EQ (&i, &n2()); | |||
| } | |||
| TEST(nullable_tests, ctor_copy) | |||
| { | |||
| int i = 5; | |||
| NullableInt i1(i); | |||
| NullableIntRef i2(i); | |||
| NullableInt n1(i1); | |||
| NullableIntRef n2(i2); | |||
| EXPECT_TRUE(static_cast<bool>(n1)); | |||
| EXPECT_TRUE(static_cast<bool>(n2)); | |||
| EXPECT_EQ (5, n1()); | |||
| EXPECT_EQ (&i, &n2()); | |||
| } | |||
| TEST(nullable_tests, ctor_move) | |||
| { | |||
| NullableString i1("test"); | |||
| NullableString n1(std::move(i1)); | |||
| EXPECT_FALSE(static_cast<bool>(i1)); | |||
| ASSERT_TRUE (static_cast<bool>(n1)); | |||
| EXPECT_EQ (std::string("test"), n1()); | |||
| } | |||
| TEST(nullable_tests, move_assignment) | |||
| { | |||
| NullableString i1("test"); | |||
| NullableString n1; | |||
| n1 = std::move(i1); | |||
| EXPECT_FALSE(static_cast<bool>(i1)); | |||
| ASSERT_TRUE (static_cast<bool>(n1)); | |||
| EXPECT_EQ (std::string("test"), n1()); | |||
| } | |||
| TEST(nullable_tests, movable_object) | |||
| { | |||
| NonCopyableTestData data(5); | |||
| NullableNonCopyableTestData tmp; | |||
| tmp = std::move(data); | |||
| ASSERT_TRUE ( tmp.has_value() ); | |||
| ASSERT_EQ ( 5, tmp.value().value ); | |||
| ASSERT_EQ ( 0, data.value ); | |||
| } | |||
| TEST(nullable_tests, hasValue_operatorBool) | |||
| { | |||
| EXPECT_FALSE(static_cast<bool>(NullableInt())); | |||
| EXPECT_FALSE(NullableInt().has_value()); | |||
| EXPECT_TRUE (static_cast<bool>(NullableInt(5))); | |||
| EXPECT_TRUE (NullableInt(5).has_value()); | |||
| } | |||
| TEST(nullable_tests, reset) | |||
| { | |||
| NullableTestData n(TestData{}); | |||
| EXPECT_TRUE (n.has_value()); | |||
| int tmp = TestData::dtorCount; | |||
| n.reset(); | |||
| EXPECT_FALSE(n.has_value()); | |||
| EXPECT_EQ (tmp + 1, TestData::dtorCount); | |||
| } | |||
| TEST(nullable_tests, value_functor) | |||
| { | |||
| NullableInt n1(5); | |||
| NullableInt n2; | |||
| EXPECT_EQ (5, n1()); | |||
| EXPECT_EQ (5, n1.value()); | |||
| EXPECT_ANY_THROW(n2()); | |||
| EXPECT_ANY_THROW(n2.value()); | |||
| } | |||
| TEST(nullable_tests, equalityCompareOperator) | |||
| { | |||
| NullableInt n1(5); | |||
| NullableInt n2(7); | |||
| NullableInt n3; | |||
| EXPECT_FALSE(n2 == n1); | |||
| EXPECT_TRUE ( 5 == n1); | |||
| EXPECT_FALSE(n3 == n1); | |||
| EXPECT_FALSE(n1 == n2); | |||
| EXPECT_FALSE( 5 == n2); | |||
| EXPECT_FALSE(n3 == n2); | |||
| EXPECT_TRUE (n1 == 5); | |||
| EXPECT_FALSE(n2 == 5); | |||
| EXPECT_FALSE(n3 == 5); | |||
| EXPECT_FALSE(n1 == n3); | |||
| EXPECT_FALSE(n2 == n3); | |||
| EXPECT_FALSE( 5 == n3); | |||
| } | |||
| TEST(nullable_tests, unequalityCompareOperator) | |||
| { | |||
| NullableInt n1(5); | |||
| NullableInt n2(7); | |||
| NullableInt n3; | |||
| EXPECT_TRUE (n2 != n1); | |||
| EXPECT_FALSE( 5 != n1); | |||
| EXPECT_FALSE(n3 != n1); | |||
| EXPECT_TRUE (n1 != n2); | |||
| EXPECT_TRUE ( 5 != n2); | |||
| EXPECT_FALSE(n3 != n2); | |||
| EXPECT_FALSE(n1 != 5); | |||
| EXPECT_TRUE (n2 != 5); | |||
| EXPECT_FALSE(n3 != 5); | |||
| EXPECT_FALSE(n1 != n3); | |||
| EXPECT_FALSE(n2 != n3); | |||
| EXPECT_FALSE( 5 != n3); | |||
| } | |||
| TEST(nullable_tests, lessCompareOperator) | |||
| { | |||
| NullableInt n1(5); | |||
| NullableInt n2(7); | |||
| NullableInt n3; | |||
| EXPECT_FALSE(n2 < n1); | |||
| EXPECT_FALSE( 5 < n1); | |||
| EXPECT_FALSE(n3 < n1); | |||
| EXPECT_TRUE (n1 < n2); | |||
| EXPECT_TRUE ( 5 < n2); | |||
| EXPECT_FALSE(n3 < n2); | |||
| EXPECT_FALSE(n1 < 5); | |||
| EXPECT_FALSE(n2 < 5); | |||
| EXPECT_FALSE(n3 < 5); | |||
| EXPECT_FALSE(n1 < n3); | |||
| EXPECT_FALSE(n2 < n3); | |||
| EXPECT_FALSE( 5 < n3); | |||
| } | |||
| TEST(nullable_tests, lessEqualCompareOperator) | |||
| { | |||
| NullableInt n1(5); | |||
| NullableInt n2(7); | |||
| NullableInt n3; | |||
| EXPECT_FALSE(n2 <= n1); | |||
| EXPECT_TRUE ( 5 <= n1); | |||
| EXPECT_FALSE(n3 <= n1); | |||
| EXPECT_TRUE (n1 <= n2); | |||
| EXPECT_TRUE ( 5 <= n2); | |||
| EXPECT_FALSE(n3 <= n2); | |||
| EXPECT_TRUE (n1 <= 5); | |||
| EXPECT_FALSE(n2 <= 5); | |||
| EXPECT_FALSE(n3 <= 5); | |||
| EXPECT_FALSE(n1 <= n3); | |||
| EXPECT_FALSE(n2 <= n3); | |||
| EXPECT_FALSE( 5 <= n3); | |||
| } | |||
| TEST(nullable_tests, greaterCompareOperator) | |||
| { | |||
| NullableInt n1(5); | |||
| NullableInt n2(7); | |||
| NullableInt n3; | |||
| EXPECT_TRUE (n2 > n1); | |||
| EXPECT_FALSE( 5 > n1); | |||
| EXPECT_FALSE(n3 > n1); | |||
| EXPECT_FALSE(n1 > n2); | |||
| EXPECT_FALSE( 5 > n2); | |||
| EXPECT_FALSE(n3 > n2); | |||
| EXPECT_FALSE(n1 > 5); | |||
| EXPECT_TRUE (n2 > 5); | |||
| EXPECT_FALSE(n3 > 5); | |||
| EXPECT_FALSE(n1 > n3); | |||
| EXPECT_FALSE(n2 > n3); | |||
| EXPECT_FALSE( 5 > n3); | |||
| } | |||
| TEST(nullable_tests, greaterEqualCompareOperator) | |||
| { | |||
| NullableInt n1(5); | |||
| NullableInt n2(7); | |||
| NullableInt n3; | |||
| EXPECT_TRUE (n2 >= n1); | |||
| EXPECT_TRUE ( 5 >= n1); | |||
| EXPECT_FALSE(n3 >= n1); | |||
| EXPECT_FALSE(n1 >= n2); | |||
| EXPECT_FALSE( 5 >= n2); | |||
| EXPECT_FALSE(n3 >= n2); | |||
| EXPECT_TRUE (n1 >= 5); | |||
| EXPECT_TRUE (n2 >= 5); | |||
| EXPECT_FALSE(n3 >= 5); | |||
| EXPECT_FALSE(n1 >= n3); | |||
| EXPECT_FALSE(n2 >= n3); | |||
| EXPECT_FALSE( 5 >= n3); | |||
| } | |||