summaryrefslogtreecommitdiffstats
path: root/third_party/rlbox/include/rlbox_stdlib_polyfill.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rlbox/include/rlbox_stdlib_polyfill.hpp')
-rw-r--r--third_party/rlbox/include/rlbox_stdlib_polyfill.hpp175
1 files changed, 175 insertions, 0 deletions
diff --git a/third_party/rlbox/include/rlbox_stdlib_polyfill.hpp b/third_party/rlbox/include/rlbox_stdlib_polyfill.hpp
new file mode 100644
index 0000000000..cf9c0117d0
--- /dev/null
+++ b/third_party/rlbox/include/rlbox_stdlib_polyfill.hpp
@@ -0,0 +1,175 @@
+#pragma once
+
+// This file is a polyfill for parts of the C++ standard library available only
+// in newer compilers. Since these are only compile time requirements, we can
+// just include these as part of the rlbox library in case the target compiler
+// doesn't support these features. For instance clang-5 which rlbox supports
+// does not support std::invocable and related functionality in <type_traits>
+// and is polyfilled here.
+//
+// This code was borrowed from clang's standard library - libc++
+//
+// Link:
+// https://github.com/llvm-mirror/libcxx/blob/master/include/type_traits
+//
+// libc++ is dual licensed under the MIT license and the UIUC License (a
+// BSD-like license) and is therefore compatible with our code base
+
+// std::invocable and friends
+
+namespace rlbox::detail::polyfill {
+
+struct __nat
+{
+ __nat() = delete;
+ __nat(const __nat&) = delete;
+ __nat& operator=(const __nat&) = delete;
+ ~__nat() = delete;
+};
+
+template<bool _Val>
+using _BoolConstant = std::integral_constant<bool, _Val>;
+
+template<class _Tp, class _Up>
+using _IsNotSame = _BoolConstant<!std::is_same<_Tp, _Up>::value>;
+
+#define INVOKE_RETURN(...) \
+ noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { return __VA_ARGS__; }
+
+template<class _Fp, class... _Args>
+inline auto helper__invoke(_Fp&& __f, _Args&&... __args)
+ INVOKE_RETURN(std::forward<_Fp>(__f)(std::forward<_Args>(__args)...))
+
+ template<class _Fp, class... _Args>
+ inline constexpr auto helper__invoke_constexpr(_Fp&& __f, _Args&&... __args)
+ INVOKE_RETURN(std::forward<_Fp>(__f)(std::forward<_Args>(__args)...))
+
+#undef INVOKE_RETURN
+
+ // __invokable
+ template<class _Ret, class _Fp, class... _Args>
+ struct __invokable_r
+{
+ template<class _XFp, class... _XArgs>
+ static auto __try_call(int)
+ -> decltype(helper__invoke(std::declval<_XFp>(),
+ std::declval<_XArgs>()...));
+ template<class _XFp, class... _XArgs>
+ static __nat __try_call(...);
+
+ // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void,
+ // or incomplete array types as required by the standard.
+ using _Result = decltype(__try_call<_Fp, _Args...>(0));
+
+ using type = typename std::conditional<
+ _IsNotSame<_Result, __nat>::value,
+ typename std::conditional<std::is_void<_Ret>::value,
+ std::true_type,
+ std::is_convertible<_Result, _Ret>>::type,
+ std::false_type>::type;
+ static const bool value = type::value;
+};
+template<class _Fp, class... _Args>
+using __invokable = __invokable_r<void, _Fp, _Args...>;
+
+template<bool _IsInvokable,
+ bool _IsCVVoid,
+ class _Ret,
+ class _Fp,
+ class... _Args>
+struct __nothrow_invokable_r_imp
+{
+ static const bool value = false;
+};
+
+template<class _Ret, class _Fp, class... _Args>
+struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...>
+{
+ typedef __nothrow_invokable_r_imp _ThisT;
+
+ template<class _Tp>
+ static void __test_noexcept(_Tp) noexcept;
+
+ static const bool value = noexcept(_ThisT::__test_noexcept<_Ret>(
+ helper__invoke(std::declval<_Fp>(), std::declval<_Args>()...)));
+};
+
+template<class _Ret, class _Fp, class... _Args>
+struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...>
+{
+ static const bool value =
+ noexcept(helper__invoke(std::declval<_Fp>(), std::declval<_Args>()...));
+};
+
+template<class _Ret, class _Fp, class... _Args>
+using __nothrow_invokable_r =
+ __nothrow_invokable_r_imp<__invokable_r<_Ret, _Fp, _Args...>::value,
+ std::is_void<_Ret>::value,
+ _Ret,
+ _Fp,
+ _Args...>;
+
+template<class _Fp, class... _Args>
+using __nothrow_invokable =
+ __nothrow_invokable_r_imp<__invokable<_Fp, _Args...>::value,
+ true,
+ void,
+ _Fp,
+ _Args...>;
+
+template<class _Fp, class... _Args>
+struct helper__invoke_of
+ : public std::enable_if<__invokable<_Fp, _Args...>::value,
+ typename __invokable_r<void, _Fp, _Args...>::_Result>
+{};
+
+// invoke_result
+
+template<class _Fn, class... _Args>
+struct invoke_result : helper__invoke_of<_Fn, _Args...>
+{};
+
+template<class _Fn, class... _Args>
+using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
+
+// is_invocable
+
+template<class _Fn, class... _Args>
+struct is_invocable
+ : std::integral_constant<bool, __invokable<_Fn, _Args...>::value>
+{};
+
+template<class _Ret, class _Fn, class... _Args>
+struct is_invocable_r
+ : std::integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value>
+{};
+
+template<class _Fn, class... _Args>
+inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
+
+template<class _Ret, class _Fn, class... _Args>
+inline constexpr bool is_invocable_r_v =
+ is_invocable_r<_Ret, _Fn, _Args...>::value;
+
+// is_nothrow_invocable
+
+template<class _Fn, class... _Args>
+struct is_nothrow_invocable
+ : std::integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value>
+{};
+
+template<class _Ret, class _Fn, class... _Args>
+struct is_nothrow_invocable_r
+ : std::integral_constant<bool,
+ __nothrow_invokable_r<_Ret, _Fn, _Args...>::value>
+{};
+
+template<class _Fn, class... _Args>
+inline constexpr bool is_nothrow_invocable_v =
+ is_nothrow_invocable<_Fn, _Args...>::value;
+
+template<class _Ret, class _Fn, class... _Args>
+inline constexpr bool is_nothrow_invocable_r_v =
+ is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
+
+}