about summary refs log tree commit diff
path: root/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h')
-rw-r--r--third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h391
1 files changed, 391 insertions, 0 deletions
diff --git a/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h b/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h
new file mode 100644
index 0000000000..00775f960c
--- /dev/null
+++ b/third_party/abseil_cpp/absl/types/internal/conformance_testing_helpers.h
@@ -0,0 +1,391 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
+
+// Checks to determine whether or not we can use abi::__cxa_demangle
+#if (defined(__ANDROID__) || defined(ANDROID)) && !defined(OS_ANDROID)
+#define ABSL_INTERNAL_OS_ANDROID
+#endif
+
+// We support certain compilers only.  See demangle.h for details.
+#if defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__))
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0
+#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \
+    !defined(__mips__)
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1
+#elif defined(__clang__) && !defined(_MSC_VER)
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1
+#else
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0
+#endif
+
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+#include "absl/utility/utility.h"
+
+#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE
+#include <cxxabi.h>
+
+#include <cstdlib>
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// Return a readable name for type T.
+template <class T>
+absl::string_view NameOfImpl() {
+// TODO(calabrese) Investigate using debugging:internal_demangle as a fallback.
+#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE
+  int status = 0;
+  char* demangled_name = nullptr;
+
+  demangled_name =
+      abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
+
+  if (status == 0 && demangled_name != nullptr) {
+    return demangled_name;
+  } else {
+    return typeid(T).name();
+  }
+#else
+  return typeid(T).name();
+#endif
+  // NOTE: We intentionally leak demangled_name so that it remains valid
+  // throughout the remainder of the program.
+}
+
+// Given a type, returns as nice of a type name as we can produce (demangled).
+//
+// Note: This currently strips cv-qualifiers and references, but that is okay
+// because we only use this internally with unqualified object types.
+template <class T>
+std::string NameOf() {
+  static const absl::string_view result = NameOfImpl<T>();
+  return std::string(result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Metafunction to check if a type is callable with no explicit arguments
+template <class Fun, class /*Enabler*/ = void>
+struct IsNullaryCallableImpl : std::false_type {};
+
+template <class Fun>
+struct IsNullaryCallableImpl<
+    Fun, absl::void_t<decltype(std::declval<const Fun&>()())>>
+    : std::true_type {
+  using result_type = decltype(std::declval<const Fun&>()());
+
+  template <class ValueType>
+  using for_type = std::is_same<ValueType, result_type>;
+
+  using void_if_true = void;
+};
+
+template <class Fun>
+struct IsNullaryCallable : IsNullaryCallableImpl<Fun> {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// A type that contains a function object that returns an instance of a type
+// that is undergoing conformance testing. This function is required to always
+// return the same value upon invocation.
+template <class Fun>
+struct GeneratorType;
+
+// A type that contains a tuple of GeneratorType<Fun> where each Fun has the
+// same return type. The result of each of the different generators should all
+// be equal values, though the underlying object representation may differ (such
+// as if one returns 0.0 and another return -0.0, or if one returns an empty
+// vector and another returns an empty vector with a different capacity.
+template <class... Funs>
+struct EquivalenceClassType;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction to check if a type is a specialization of EquivalenceClassType
+template <class T>
+struct IsEquivalenceClass : std::false_type {};
+
+template <>
+struct IsEquivalenceClass<EquivalenceClassType<>> : std::true_type {
+  using self = IsEquivalenceClass;
+
+  // A metafunction to check if this EquivalenceClassType is a valid
+  // EquivalenceClassType for a type `ValueType` that is undergoing testing
+  template <class ValueType>
+  using for_type = std::true_type;
+};
+
+template <class Head, class... Tail>
+struct IsEquivalenceClass<EquivalenceClassType<Head, Tail...>>
+    : std::true_type {
+  using self = IsEquivalenceClass;
+
+  // The type undergoing conformance testing that this EquivalenceClass
+  // corresponds to
+  using result_type = typename IsNullaryCallable<Head>::result_type;
+
+  // A metafunction to check if this EquivalenceClassType is a valid
+  // EquivalenceClassType for a type `ValueType` that is undergoing testing
+  template <class ValueType>
+  using for_type = std::is_same<ValueType, result_type>;
+};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// A type that contains an ordered series of EquivalenceClassTypes, where the
+// the function object of each underlying GeneratorType has the same return type
+//
+// These equivalence classes are required to be in a logical ascending order
+// that is consistent with comparison operators that are defined for the return
+// type of each GeneratorType, if any.
+template <class... EqClasses>
+struct OrderedEquivalenceClasses;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction to determine the return type of the function object contained
+// in a GeneratorType specialization.
+template <class T>
+struct ResultOfGenerator {};
+
+template <class Fun>
+struct ResultOfGenerator<GeneratorType<Fun>> {
+  using type = decltype(std::declval<const Fun&>()());
+};
+
+template <class Fun>
+using ResultOfGeneratorT = typename ResultOfGenerator<GeneratorType<Fun>>::type;
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction that yields true iff each of Funs is a GeneratorType
+// specialization and they all contain functions with the same return type
+template <class /*Enabler*/, class... Funs>
+struct AreGeneratorsWithTheSameReturnTypeImpl : std::false_type {};
+
+template <>
+struct AreGeneratorsWithTheSameReturnTypeImpl<void> : std::true_type {};
+
+template <class Head, class... Tail>
+struct AreGeneratorsWithTheSameReturnTypeImpl<
+    typename std::enable_if<absl::conjunction<std::is_same<
+        ResultOfGeneratorT<Head>, ResultOfGeneratorT<Tail>>...>::value>::type,
+    Head, Tail...> : std::true_type {};
+
+template <class... Funs>
+struct AreGeneratorsWithTheSameReturnType
+    : AreGeneratorsWithTheSameReturnTypeImpl<void, Funs...>::type {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction that yields true iff each of Funs is an EquivalenceClassType
+// specialization and they all contain GeneratorType specializations that have
+// the same return type
+template <class... EqClasses>
+struct AreEquivalenceClassesOfTheSameType {
+  static_assert(sizeof...(EqClasses) != sizeof...(EqClasses), "");
+};
+
+template <>
+struct AreEquivalenceClassesOfTheSameType<> : std::true_type {
+  using self = AreEquivalenceClassesOfTheSameType;
+
+  // Metafunction to check that a type is the same as all of the equivalence
+  // classes, if any.
+  // Note: In this specialization there are no equivalence classes, so the
+  // value type is always compatible.
+  template <class /*ValueType*/>
+  using for_type = std::true_type;
+};
+
+template <class... Funs>
+struct AreEquivalenceClassesOfTheSameType<EquivalenceClassType<Funs...>>
+    : std::true_type {
+  using self = AreEquivalenceClassesOfTheSameType;
+
+  // Metafunction to check that a type is the same as all of the equivalence
+  // classes, if any.
+  template <class ValueType>
+  using for_type = typename IsEquivalenceClass<
+      EquivalenceClassType<Funs...>>::template for_type<ValueType>;
+};
+
+template <class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+    EquivalenceClassType<>, EquivalenceClassType<>, TailEqClasses...>
+    : AreEquivalenceClassesOfTheSameType<TailEqClasses...>::self {};
+
+template <class HeadNextFun, class... TailNextFuns, class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+    EquivalenceClassType<>, EquivalenceClassType<HeadNextFun, TailNextFuns...>,
+    TailEqClasses...>
+    : AreEquivalenceClassesOfTheSameType<
+          EquivalenceClassType<HeadNextFun, TailNextFuns...>,
+          TailEqClasses...>::self {};
+
+template <class HeadHeadFun, class... TailHeadFuns, class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+    EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, EquivalenceClassType<>,
+    TailEqClasses...>
+    : AreEquivalenceClassesOfTheSameType<
+          EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
+          TailEqClasses...>::self {};
+
+template <class HeadHeadFun, class... TailHeadFuns, class HeadNextFun,
+          class... TailNextFuns, class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+    EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
+    EquivalenceClassType<HeadNextFun, TailNextFuns...>, TailEqClasses...>
+    : absl::conditional_t<
+          IsNullaryCallable<HeadNextFun>::template for_type<
+              typename IsNullaryCallable<HeadHeadFun>::result_type>::value,
+          AreEquivalenceClassesOfTheSameType<
+              EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
+              TailEqClasses...>,
+          std::false_type> {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Execute a function for each passed-in parameter.
+template <class Fun, class... Cases>
+void ForEachParameter(const Fun& fun, const Cases&... cases) {
+  const std::initializer_list<bool> results = {
+      (static_cast<void>(fun(cases)), true)...};
+
+  (void)results;
+}
+
+// Execute a function on each passed-in parameter (using a bound function).
+template <class Fun>
+struct ForEachParameterFun {
+  template <class... T>
+  void operator()(const T&... cases) const {
+    (ForEachParameter)(fun, cases...);
+  }
+
+  Fun fun;
+};
+
+// Execute a function on each element of a tuple.
+template <class Fun, class Tup>
+void ForEachTupleElement(const Fun& fun, const Tup& tup) {
+  absl::apply(ForEachParameterFun<Fun>{fun}, tup);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Execute a function for each combination of two elements of a tuple, including
+// combinations of an element with itself.
+template <class Fun, class... T>
+struct ForEveryTwoImpl {
+  template <class Lhs>
+  struct WithBoundLhs {
+    template <class Rhs>
+    void operator()(const Rhs& rhs) const {
+      fun(lhs, rhs);
+    }
+
+    Fun fun;
+    Lhs lhs;
+  };
+
+  template <class Lhs>
+  void operator()(const Lhs& lhs) const {
+    (ForEachTupleElement)(WithBoundLhs<Lhs>{fun, lhs}, args);
+  }
+
+  Fun fun;
+  std::tuple<T...> args;
+};
+
+template <class Fun, class... T>
+void ForEveryTwo(const Fun& fun, std::tuple<T...> args) {
+  (ForEachTupleElement)(ForEveryTwoImpl<Fun, T...>{fun, args}, args);
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Insert all values into an associative container
+template<class Container>
+void InsertEach(Container* cont) {
+}
+
+template<class Container, class H, class... T>
+void InsertEach(Container* cont, H&& head, T&&... tail) {
+  cont->insert(head);
+  (InsertEach)(cont, tail...);
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+// A template with a nested "Invoke" static-member-function that executes a
+// passed-in Callable when `Condition` is true, otherwise it ignores the
+// Callable. This is useful for executing a function object with a condition
+// that corresponds to whether or not the Callable can be safely instantiated.
+// It has some overlapping uses with C++17 `if constexpr`.
+template <bool Condition>
+struct If;
+
+template <>
+struct If</*Condition =*/false> {
+  template <class Fun, class... P>
+  static void Invoke(const Fun& /*fun*/, P&&... /*args*/) {}
+};
+
+template <>
+struct If</*Condition =*/true> {
+  template <class Fun, class... P>
+  static void Invoke(const Fun& fun, P&&... args) {
+    // TODO(calabrese) Use std::invoke equivalent instead of function-call.
+    fun(absl::forward<P>(args)...);
+  }
+};
+
+//
+// ABSL_INTERNAL_STRINGIZE(...)
+//
+// This variadic macro transforms its arguments into a c-string literal after
+// expansion.
+//
+// Example:
+//
+//   ABSL_INTERNAL_STRINGIZE(std::array<int, 10>)
+//
+// Results in:
+//
+//   "std::array<int, 10>"
+#define ABSL_INTERNAL_STRINGIZE(...) ABSL_INTERNAL_STRINGIZE_IMPL((__VA_ARGS__))
+#define ABSL_INTERNAL_STRINGIZE_IMPL(arg) ABSL_INTERNAL_STRINGIZE_IMPL2 arg
+#define ABSL_INTERNAL_STRINGIZE_IMPL2(...) #__VA_ARGS__
+
+}  // namespace types_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_