summaryrefslogtreecommitdiff
path: root/gdbsupport/traits.h
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport/traits.h')
-rw-r--r--gdbsupport/traits.h67
1 files changed, 67 insertions, 0 deletions
diff --git a/gdbsupport/traits.h b/gdbsupport/traits.h
index 2a6f00654c7..93b609ac109 100644
--- a/gdbsupport/traits.h
+++ b/gdbsupport/traits.h
@@ -52,6 +52,73 @@ struct make_void { typedef void type; };
template<typename... Ts>
using void_t = typename make_void<Ts...>::type;
+/* Implementation of the detection idiom:
+
+ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf
+ - http://en.cppreference.com/w/cpp/experimental/is_detected
+
+*/
+
+struct nonesuch
+{
+ nonesuch () = delete;
+ ~nonesuch () = delete;
+ nonesuch (const nonesuch &) = delete;
+ void operator= (const nonesuch &) = delete;
+};
+
+namespace detection_detail {
+/* Implementation of the detection idiom (negative case). */
+template<typename Default, typename AlwaysVoid,
+ template<typename...> class Op, typename... Args>
+struct detector
+{
+ using value_t = std::false_type;
+ using type = Default;
+};
+
+/* Implementation of the detection idiom (positive case). */
+template<typename Default, template<typename...> class Op, typename... Args>
+struct detector<Default, void_t<Op<Args...>>, Op, Args...>
+{
+ using value_t = std::true_type;
+ using type = Op<Args...>;
+};
+
+/* Detect whether Op<Args...> is a valid type, use Default if not. */
+template<typename Default, template<typename...> class Op,
+ typename... Args>
+using detected_or = detector<Default, void, Op, Args...>;
+
+/* Op<Args...> if that is a valid type, otherwise Default. */
+template<typename Default, template<typename...> class Op,
+ typename... Args>
+using detected_or_t
+ = typename detected_or<Default, Op, Args...>::type;
+
+} /* detection_detail */
+
+template<template<typename...> class Op, typename... Args>
+using is_detected
+ = typename detection_detail::detector<nonesuch, void, Op, Args...>::value_t;
+
+template<template<typename...> class Op, typename... Args>
+using detected_t
+ = typename detection_detail::detector<nonesuch, void, Op, Args...>::type;
+
+template<typename Default, template<typename...> class Op, typename... Args>
+using detected_or = detection_detail::detected_or<Default, Op, Args...>;
+
+template<typename Default, template<typename...> class Op, typename... Args>
+using detected_or_t = typename detected_or<Default, Op, Args...>::type;
+
+template<typename Expected, template<typename...> class Op, typename... Args>
+using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
+
+template<typename To, template<typename...> class Op, typename... Args>
+using is_detected_convertible
+ = std::is_convertible<detected_t<Op, Args...>, To>;
+
/* A few trait helpers, mainly stolen from libstdc++. Uppercase
because "and/or", etc. are reserved keywords. */