#define LLVM_ADT_STLEXTRAS_H
#include "llvm/Support/Compiler.h"
+#include <cassert>
#include <cstddef> // for std::size_t
#include <cstdlib> // for qsort
#include <functional>
}
};
+/// An efficient, type-erasing, non-owning reference to a callable. This is
+/// intended for use as the type of a function parameter that is not used
+/// after the function in question returns.
+///
+/// This class does not own the callable, so it is not in general safe to store
+/// a function_ref.
+template<typename Fn> class function_ref;
+
+#if LLVM_HAS_VARIADIC_TEMPLATES
+
+template<typename Ret, typename ...Params>
+class function_ref<Ret(Params...)> {
+ Ret (*callback)(intptr_t callable, Params ...params);
+ intptr_t callable;
+
+ template<typename Callable>
+ static Ret callback_fn(intptr_t callable, Params ...params) {
+ return (*reinterpret_cast<Callable*>(callable))(
+ std::forward<Params>(params)...);
+ }
+
+public:
+ template <typename Callable>
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
+ : callback(callback_fn<typename std::remove_reference<Callable>::type>),
+ callable(reinterpret_cast<intptr_t>(&callable)) {}
+ Ret operator()(Params ...params) const {
+ return callback(callable, std::forward<Params>(params)...);
+ }
+};
+
+#else
+
+template<typename Ret>
+class function_ref<Ret()> {
+ Ret (*callback)(intptr_t callable);
+ intptr_t callable;
+
+ template<typename Callable>
+ static Ret callback_fn(intptr_t callable) {
+ return (*reinterpret_cast<Callable*>(callable))();
+ }
+
+public:
+ template<typename Callable>
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
+ : callback(callback_fn<typename std::remove_reference<Callable>::type>),
+ callable(reinterpret_cast<intptr_t>(&callable)) {}
+ Ret operator()() const { return callback(callable); }
+};
+
+template<typename Ret, typename Param1>
+class function_ref<Ret(Param1)> {
+ Ret (*callback)(intptr_t callable, Param1 param1);
+ intptr_t callable;
+
+ template<typename Callable>
+ static Ret callback_fn(intptr_t callable, Param1 param1) {
+ return (*reinterpret_cast<Callable*>(callable))(
+ std::forward<Param1>(param1));
+ }
+
+public:
+ template<typename Callable>
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
+ : callback(callback_fn<typename std::remove_reference<Callable>::type>),
+ callable(reinterpret_cast<intptr_t>(&callable)) {}
+ Ret operator()(Param1 param1) {
+ return callback(callable, std::forward<Param1>(param1));
+ }
+};
+
+template<typename Ret, typename Param1, typename Param2>
+class function_ref<Ret(Param1, Param2)> {
+ Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2);
+ intptr_t callable;
+
+ template<typename Callable>
+ static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2) {
+ return (*reinterpret_cast<Callable*>(callable))(
+ std::forward<Param1>(param1),
+ std::forward<Param2>(param2));
+ }
+
+public:
+ template<typename Callable>
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
+ : callback(callback_fn<typename std::remove_reference<Callable>::type>),
+ callable(reinterpret_cast<intptr_t>(&callable)) {}
+ Ret operator()(Param1 param1, Param2 param2) {
+ return callback(callable,
+ std::forward<Param1>(param1),
+ std::forward<Param2>(param2));
+ }
+};
+
+template<typename Ret, typename Param1, typename Param2, typename Param3>
+class function_ref<Ret(Param1, Param2, Param3)> {
+ Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2, Param3 param3);
+ intptr_t callable;
+
+ template<typename Callable>
+ static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2,
+ Param3 param3) {
+ return (*reinterpret_cast<Callable*>(callable))(
+ std::forward<Param1>(param1),
+ std::forward<Param2>(param2),
+ std::forward<Param3>(param3));
+ }
+
+public:
+ template<typename Callable>
+ function_ref(Callable &&callable,
+ typename std::enable_if<
+ !std::is_same<typename std::remove_reference<Callable>::type,
+ function_ref>::value>::type * = nullptr)
+ : callback(callback_fn<typename std::remove_reference<Callable>::type>),
+ callable(reinterpret_cast<intptr_t>(&callable)) {}
+ Ret operator()(Param1 param1, Param2 param2, Param3 param3) {
+ return callback(callable,
+ std::forward<Param1>(param1),
+ std::forward<Param2>(param2),
+ std::forward<Param3>(param3));
+ }
+};
+
+#endif
+
// deleter - Very very very simple method that is used to invoke operator
// delete on something. It is used like this:
//
return N;
}
-/// array_pod_sort_comparator - This is helper function for array_pod_sort,
-/// which just uses operator< on T.
+/// Adapt std::less<T> for array_pod_sort.
template<typename T>
inline int array_pod_sort_comparator(const void *P1, const void *P2) {
- if (*reinterpret_cast<const T*>(P1) < *reinterpret_cast<const T*>(P2))
+ if (std::less<T>()(*reinterpret_cast<const T*>(P1),
+ *reinterpret_cast<const T*>(P2)))
return -1;
- if (*reinterpret_cast<const T*>(P2) < *reinterpret_cast<const T*>(P1))
+ if (std::less<T>()(*reinterpret_cast<const T*>(P2),
+ *reinterpret_cast<const T*>(P1)))
return 1;
return 0;
}
/// possible.
///
/// This function assumes that you have simple POD-like types that can be
-/// compared with operator< and can be moved with memcpy. If this isn't true,
+/// compared with std::less and can be moved with memcpy. If this isn't true,
/// you should use std::sort.
///
/// NOTE: If qsort_r were portable, we could allow a custom comparator and
#endif
+struct FreeDeleter {
+ void operator()(void* v) {
+ ::free(v);
+ }
+};
+
+template<typename First, typename Second>
+struct pair_hash {
+ size_t operator()(const std::pair<First, Second> &P) const {
+ return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
+ }
+};
+
+/// A functor like C++14's std::less<void> in its absence.
+struct less {
+ template <typename A, typename B> bool operator()(A &&a, B &&b) const {
+ return std::forward<A>(a) < std::forward<B>(b);
+ }
+};
+
+/// A functor like C++14's std::equal<void> in its absence.
+struct equal {
+ template <typename A, typename B> bool operator()(A &&a, B &&b) const {
+ return std::forward<A>(a) == std::forward<B>(b);
+ }
+};
+
+/// Binary functor that adapts to any other binary functor after dereferencing
+/// operands.
+template <typename T> struct deref {
+ T func;
+ // Could be further improved to cope with non-derivable functors and
+ // non-binary functors (should be a variadic template member function
+ // operator()).
+ template <typename A, typename B>
+ auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) {
+ assert(lhs);
+ assert(rhs);
+ return func(*lhs, *rhs);
+ }
+};
+
} // End llvm namespace
#endif