about summary refs log tree commit diff
path: root/third_party/immer/immer/detail/type_traits.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/immer/immer/detail/type_traits.hpp')
-rw-r--r--third_party/immer/immer/detail/type_traits.hpp223
1 files changed, 223 insertions, 0 deletions
diff --git a/third_party/immer/immer/detail/type_traits.hpp b/third_party/immer/immer/detail/type_traits.hpp
new file mode 100644
index 0000000000..afb2652c55
--- /dev/null
+++ b/third_party/immer/immer/detail/type_traits.hpp
@@ -0,0 +1,223 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+namespace immer {
+namespace detail {
+
+template <typename... Ts>
+struct make_void
+{
+    using type = void;
+};
+
+template <typename... Ts>
+using void_t = typename make_void<Ts...>::type;
+
+template <typename T, typename = void>
+struct is_dereferenceable : std::false_type
+{};
+
+template <typename T>
+struct is_dereferenceable<T, void_t<decltype(*(std::declval<T&>()))>>
+    : std::true_type
+{};
+
+template <typename T>
+constexpr bool is_dereferenceable_v = is_dereferenceable<T>::value;
+
+template <typename T, typename U = T, typename = void>
+struct is_equality_comparable : std::false_type
+{};
+
+template <typename T, typename U>
+struct is_equality_comparable<
+    T,
+    U,
+    std::enable_if_t<std::is_same<bool,
+                                  decltype(std::declval<T&>() ==
+                                           std::declval<U&>())>::value>>
+    : std::true_type
+{};
+
+template <typename T, typename U = T>
+constexpr bool is_equality_comparable_v = is_equality_comparable<T, U>::value;
+
+template <typename T, typename U = T, typename = void>
+struct is_inequality_comparable : std::false_type
+{};
+
+template <typename T, typename U>
+struct is_inequality_comparable<
+    T,
+    U,
+    std::enable_if_t<std::is_same<bool,
+                                  decltype(std::declval<T&>() !=
+                                           std::declval<U&>())>::value>>
+    : std::true_type
+{};
+
+template <typename T, typename U = T>
+constexpr bool is_inequality_comparable_v =
+    is_inequality_comparable<T, U>::value;
+
+template <typename T, typename = void>
+struct is_preincrementable : std::false_type
+{};
+
+template <typename T>
+struct is_preincrementable<
+    T,
+    std::enable_if_t<std::is_same<T&, decltype(++(std::declval<T&>()))>::value>>
+    : std::true_type
+{};
+
+template <typename T>
+constexpr bool is_preincrementable_v = is_preincrementable<T>::value;
+
+template <typename T, typename U = T, typename = void>
+struct is_subtractable : std::false_type
+{};
+
+template <typename T, typename U>
+struct is_subtractable<
+    T,
+    U,
+    void_t<decltype(std::declval<T&>() - std::declval<U&>())>> : std::true_type
+{};
+
+template <typename T, typename U = T>
+constexpr bool is_subtractable_v = is_subtractable<T, U>::value;
+
+namespace swappable {
+
+using std::swap;
+
+template <typename T, typename U, typename = void>
+struct with : std::false_type
+{};
+
+// Does not account for non-referenceable types
+template <typename T, typename U>
+struct with<T,
+            U,
+            void_t<decltype(swap(std::declval<T&>(), std::declval<U&>())),
+                   decltype(swap(std::declval<U&>(), std::declval<T&>()))>>
+    : std::true_type
+{};
+
+} // namespace swappable
+
+template <typename T, typename U>
+using is_swappable_with = swappable::with<T, U>;
+
+template <typename T>
+using is_swappable = is_swappable_with<T, T>;
+
+template <typename T>
+constexpr bool is_swappable_v = is_swappable_with<T&, T&>::value;
+
+template <typename T, typename = void>
+struct is_iterator : std::false_type
+{};
+
+// See http://en.cppreference.com/w/cpp/concept/Iterator
+template <typename T>
+struct is_iterator<
+    T,
+    void_t<
+        std::enable_if_t<is_preincrementable_v<T> &&
+                         is_dereferenceable_v<T>
+                         // accounts for non-referenceable types
+                         && std::is_copy_constructible<T>::value &&
+                         std::is_copy_assignable<T>::value &&
+                         std::is_destructible<T>::value && is_swappable_v<T>>,
+        typename std::iterator_traits<T>::value_type,
+        typename std::iterator_traits<T>::difference_type,
+        typename std::iterator_traits<T>::reference,
+        typename std::iterator_traits<T>::pointer,
+        typename std::iterator_traits<T>::iterator_category>> : std::true_type
+{};
+
+template <typename T>
+constexpr bool is_iterator_v = is_iterator<T>::value;
+
+template <typename T, typename U, typename = void>
+struct compatible_sentinel : std::false_type
+{};
+
+template <typename T, typename U>
+struct compatible_sentinel<
+    T,
+    U,
+    std::enable_if_t<is_iterator_v<T> && is_equality_comparable_v<T, U> &&
+                     is_inequality_comparable_v<T, U>>> : std::true_type
+{};
+
+template <typename T, typename U>
+constexpr bool compatible_sentinel_v = compatible_sentinel<T, U>::value;
+
+template <typename T, typename = void>
+struct is_forward_iterator : std::false_type
+{};
+
+template <typename T>
+struct is_forward_iterator<
+    T,
+    std::enable_if_t<is_iterator_v<T> &&
+                     std::is_base_of<std::forward_iterator_tag,
+                                     typename std::iterator_traits<
+                                         T>::iterator_category>::value>>
+    : std::true_type
+{};
+
+template <typename T>
+constexpr bool is_forward_iterator_v = is_forward_iterator<T>::value;
+
+template <typename T, typename U, typename = void>
+struct std_distance_supports : std::false_type
+{};
+
+template <typename T, typename U>
+struct std_distance_supports<
+    T,
+    U,
+    void_t<decltype(std::distance(std::declval<T>(), std::declval<U>()))>>
+    : std::true_type
+{};
+
+template <typename T, typename U>
+constexpr bool std_distance_supports_v = std_distance_supports<T, U>::value;
+
+template <typename T, typename U, typename V, typename = void>
+struct std_uninitialized_copy_supports : std::false_type
+{};
+
+template <typename T, typename U, typename V>
+struct std_uninitialized_copy_supports<
+    T,
+    U,
+    V,
+    void_t<decltype(std::uninitialized_copy(
+        std::declval<T>(), std::declval<U>(), std::declval<V>()))>>
+    : std::true_type
+{};
+
+template <typename T, typename U, typename V>
+constexpr bool std_uninitialized_copy_supports_v =
+    std_uninitialized_copy_supports<T, U, V>::value;
+
+} // namespace detail
+} // namespace immer