summaryrefslogtreecommitdiff
path: root/Rx
diff options
context:
space:
mode:
authorKirk Shoop <kirk.shoop@microsoft.com>2016-03-09 13:10:16 -0800
committerKirk Shoop <kirk.shoop@microsoft.com>2016-03-09 13:12:22 -0800
commited0a48f997bf6cbed155643fdb6c746677635067 (patch)
tree1104bd96be84772d570ad87107081e9a078c11e8 /Rx
parent3092af8c41d5fb5f8ad9f441c9412bd910045961 (diff)
downloadRxCpp-ed0a48f997bf6cbed155643fdb6c746677635067.tar.gz
support hash of enum using underlying_type by default.
can be forced to use hash with the actual enum type #define RXCPP_FORCE_HASH_ENUM 1
Diffstat (limited to 'Rx')
-rw-r--r--Rx/v2/src/rxcpp/rx-includes.hpp46
-rw-r--r--Rx/v2/src/rxcpp/rx-util.hpp7
-rw-r--r--Rx/v2/test/operators/distinct.cpp50
3 files changed, 94 insertions, 9 deletions
diff --git a/Rx/v2/src/rxcpp/rx-includes.hpp b/Rx/v2/src/rxcpp/rx-includes.hpp
index cc473f6..51a96eb 100644
--- a/Rx/v2/src/rxcpp/rx-includes.hpp
+++ b/Rx/v2/src/rxcpp/rx-includes.hpp
@@ -55,12 +55,31 @@
#endif
+//
+// control std::hash<> of enum
+// force with RXCPP_FORCE_HASH_ENUM & RXCPP_FORCE_HASH_ENUM_UNDERLYING
+// in time use ifdef to detect library support for std::hash<> of enum
+//
+#define RXCPP_HASH_ENUM 0
+#define RXCPP_HASH_ENUM_UNDERLYING 1
+
#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
#define RXCPP_USE_WINRT 0
#else
#define RXCPP_USE_WINRT 1
#endif
+#if defined(__APPLE__) && defined(__MACH__)
+#include <TargetConditionals.h>
+#if (TARGET_OS_IPHONE == 1) || (TARGET_IPHONE_SIMULATOR == 1)
+#define RXCPP_ON_IOS
+#endif
+#endif
+
+#if defined(__ANDROID__)
+#define RXCPP_ON_ANDROID
+#endif
+
#if defined(RXCPP_FORCE_USE_VARIADIC_TEMPLATES)
#undef RXCPP_USE_VARIADIC_TEMPLATES
#define RXCPP_USE_VARIADIC_TEMPLATES RXCPP_FORCE_USE_VARIADIC_TEMPLATES
@@ -81,20 +100,29 @@
#define RXCPP_USE_WINRT RXCPP_FORCE_USE_WINRT
#endif
-#if defined(_MSC_VER) && !RXCPP_USE_VARIADIC_TEMPLATES
-// resolve args needs enough to store all the possible resolved args
-#define _VARIADIC_MAX 10
+#if defined(RXCPP_FORCE_HASH_ENUM)
+#undef RXCPP_HASH_ENUM
+#define RXCPP_HASH_ENUM RXCPP_FORCE_HASH_ENUM
#endif
-#if defined(__APPLE__) && defined(__MACH__)
-#include <TargetConditionals.h>
-#if (TARGET_OS_IPHONE == 1) || (TARGET_IPHONE_SIMULATOR == 1)
-#define RXCPP_ON_IOS
+#if defined(RXCPP_FORCE_HASH_ENUM_UNDERLYING)
+#undef RXCPP_HASH_ENUM_UNDERLYING
+#define RXCPP_HASH_ENUM_UNDERLYING RXCPP_FORCE_HASH_ENUM_UNDERLYING
#endif
+
+#if defined(RXCPP_FORCE_ON_IOS)
+#undef RXCPP_ON_IOS
+#define RXCPP_ON_IOS RXCPP_FORCE_ON_IOS
#endif
-#if defined(__ANDROID__)
-#define RXCPP_ON_ANDROID
+#if defined(RXCPP_FORCE_ON_ANDROID)
+#undef RXCPP_ON_ANDROID
+#define RXCPP_ON_ANDROID RXCPP_FORCE_ON_ANDROID
+#endif
+
+#if defined(_MSC_VER) && !RXCPP_USE_VARIADIC_TEMPLATES
+// resolve args needs enough to store all the possible resolved args
+#define _VARIADIC_MAX 10
#endif
#pragma push_macro("min")
diff --git a/Rx/v2/src/rxcpp/rx-util.hpp b/Rx/v2/src/rxcpp/rx-util.hpp
index d25b76f..a4fb758 100644
--- a/Rx/v2/src/rxcpp/rx-util.hpp
+++ b/Rx/v2/src/rxcpp/rx-util.hpp
@@ -705,9 +705,16 @@ namespace rxu=util;
template <class T, typename = void>
struct filtered_hash;
+#if RXCPP_HASH_ENUM
template <class T>
struct filtered_hash<T, typename std::enable_if<std::is_enum<T>::value>::type> : std::hash<T> {
};
+#elif RXCPP_HASH_ENUM_UNDERLYING
+template <class T>
+struct filtered_hash<T, typename std::enable_if<std::is_enum<T>::value>::type> : std::hash<typename std::underlying_type<T>::type> {
+};
+#endif
+
template <class T>
struct filtered_hash<T, typename std::enable_if<std::is_integral<T>::value>::type> : std::hash<T> {
};
diff --git a/Rx/v2/test/operators/distinct.cpp b/Rx/v2/test/operators/distinct.cpp
index 77c69cd..84ce6ea 100644
--- a/Rx/v2/test/operators/distinct.cpp
+++ b/Rx/v2/test/operators/distinct.cpp
@@ -338,4 +338,54 @@ SCENARIO("distinct - strings", "[distinct][operators]"){
}
}
+}
+
+SCENARIO("distinct - enum", "[distinct][operators]"){
+ enum Value {
+ A,
+ B,
+ C
+ };
+ GIVEN("a source"){
+ auto sc = rxsc::make_test();
+ auto w = sc.create_worker();
+ const rxsc::test::messages<Value> on;
+
+ auto xs = sc.make_hot_observable({
+ on.next(150, Value::A),
+ on.next(210, Value::A),
+ on.next(220, Value::B),
+ on.next(230, Value::B),
+ on.next(240, Value::B),
+ on.completed(250)
+ });
+
+ WHEN("distinct values are taken"){
+
+ auto res = w.start(
+ [xs]() {
+ return xs.distinct();
+ }
+ );
+
+ THEN("the output only contains distinct items sent while subscribed"){
+ auto required = rxu::to_vector({
+ on.next(210, Value::A),
+ on.next(220, Value::B),
+ on.completed(250)
+ });
+ auto actual = res.get_observer().messages();
+ REQUIRE(required == actual);
+ }
+
+ THEN("there was 1 subscription/unsubscription to the source"){
+ auto required = rxu::to_vector({
+ on.subscribe(200, 250)
+ });
+ auto actual = xs.subscriptions();
+ REQUIRE(required == actual);
+ }
+
+ }
+ }
} \ No newline at end of file