+/*
+ * Malloc an object of type AllocatedType, asserting that AllocatedType can be safely malloc-ed (is
+ * trivially constructible).
+ */
+template <typename AllocatedType>
+AllocatedType *malloc()
+{
+ static_assert(can_malloc<AllocatedType>::value, "type can be malloc'ed");
+ return (AllocatedType *) malloc(sizeof(AllocatedType));
+}
+
+/*
+ * Malloc a buffer of size `size`, asserting that AllocatedType can be safely
+ * malloc-ed (is trivially constructible).
+ */
+template <typename AllocatedType>
+AllocatedType *malloc(size_t size)
+{
+ static_assert(can_malloc<AllocatedType>::value, "type can be malloc'ed");
+ return (AllocatedType *) malloc(size);
+}
+
+/*
+ * Prevent using `free` on types that are non-POD.
+ *
+ * Declare a delete prototype of free if the parameter type is not safe to free
+ * (non-POD).
+ *
+ * If the parameter is a pointer to void, we can't check if what is pointed
+ * to is safe to free or not, as we don't know what is pointed to. Ideally,
+ * all calls to free would be with a typed pointer, but there are too many
+ * instances of passing a pointer to void to enforce that right now. So allow
+ * pointers to void, these will not be checked.
+ */
+
+template <typename FreedType>
+struct can_free {
+ /*
+ * gcc versions before 5.0 lack some type traits defined in C++11.
+ * Since in this instance we use the trait to prevent misuses
+ * of free (and statically assert) and not to generate different
+ * code based on this property, simply set value to true and allow
+ * the code to compile. Anyone using a contemporary compiler will
+ * catch the error.
+ */
+#if __GNUG__ && __GNUC__ < 5
+ static constexpr bool value = true;
+#else
+ static constexpr bool value = std::is_trivially_destructible<FreedType>::value ||
+ std::is_void<FreedType>::value;
+#endif
+};
+
+template <typename FreedType, typename = typename std::enable_if<!can_free<FreedType>::value>::type>
+void free(FreedType *p) = delete;
+
+template <typename InitializedType>
+struct can_memset {
+ static constexpr bool value = std::is_pod<InitializedType>::value ||
+ std::is_void<InitializedType>::value;
+};
+
+template <typename InitializedType,
+ typename = typename std::enable_if<!can_memset<InitializedType>::value>::type>
+void *memset(InitializedType *s, int c, size_t n) = delete;
+
+template <typename T>
+struct can_memcpy {
+ /*
+ * gcc versions before 5.0 lack some type traits defined in C++11.
+ * Since in this instance we use the trait to prevent misuses
+ * of memcpy (and statically assert) and not to generate different
+ * code based on this property, simply set value to true and allow
+ * the code to compile. Anyone using a contemporary compiler will
+ * catch the error.
+ */
+#if __GNUG__ && __GNUC__ < 5
+ static constexpr bool value = true;
+#else
+ static constexpr bool value = std::is_trivially_copyable<T>::value;
+#endif
+};
+
+template <typename DestinationType,
+ typename SourceType,
+ typename = typename std::enable_if<!can_memcpy<DestinationType>::value>::type,
+ typename = typename std::enable_if<!can_memcpy<SourceType>::value>::type>
+void *memcpy(DestinationType *d, const SourceType *s, size_t n) = delete;
+
+template <typename MovedType>
+struct can_memmove {
+ /*
+ * gcc versions before 5.0 lack some type traits defined in C++11.
+ * Since in this instance we use the trait to prevent misuses
+ * of memmove (and statically assert) and not to generate different
+ * code based on this property, simply set value to true and allow
+ * the code to compile. Anyone using a contemporary compiler will
+ * catch the error.
+ */
+#if __GNUG__ && __GNUC__ < 5
+ static constexpr bool value = true;
+#else
+ static constexpr bool value = std::is_trivially_copyable<MovedType>::value;
+#endif
+};
+
+template <typename DestinationType,
+ typename SourceType,
+ typename = typename std::enable_if<!can_memmove<DestinationType>::value>::type,
+ typename = typename std::enable_if<!can_memmove<SourceType>::value>::type>
+void *memmove(DestinationType *d, const SourceType *s, size_t n) = delete;
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) (sizeof(array) / (sizeof((array)[0])))