| //===- FormatVariadicDetails.h - Helpers for FormatVariadic.h ----*- C++-*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H |
| #define LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H |
| |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| #include <type_traits> |
| |
| namespace llvm { |
| template <typename T, typename Enable = void> struct format_provider {}; |
| |
| namespace detail { |
| class format_adapter { |
| protected: |
| virtual ~format_adapter() {} |
| |
| public: |
| virtual void format(raw_ostream &S, StringRef Options) = 0; |
| }; |
| |
| template <typename T> class provider_format_adapter : public format_adapter { |
| T Item; |
| |
| public: |
| explicit provider_format_adapter(T &&Item) : Item(Item) {} |
| |
| void format(llvm::raw_ostream &S, StringRef Options) override { |
| format_provider<typename std::decay<T>::type>::format(Item, S, Options); |
| } |
| }; |
| |
| template <typename T> class missing_format_adapter; |
| |
| // Test if format_provider<T> is defined on T and contains a member function |
| // with the signature: |
| // static void format(const T&, raw_stream &, StringRef); |
| // |
| template <class T> class has_FormatProvider { |
| public: |
| using Decayed = typename std::decay<T>::type; |
| typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &, |
| StringRef); |
| |
| template <typename U> |
| static char test(SameType<Signature_format, &U::format> *); |
| |
| template <typename U> static double test(...); |
| |
| static bool const value = |
| (sizeof(test<llvm::format_provider<Decayed>>(nullptr)) == 1); |
| }; |
| |
| // Simple template that decides whether a type T should use the member-function |
| // based format() invocation. |
| template <typename T> |
| struct uses_format_member |
| : public std::integral_constant< |
| bool, |
| std::is_base_of<format_adapter, |
| typename std::remove_reference<T>::type>::value> {}; |
| |
| // Simple template that decides whether a type T should use the format_provider |
| // based format() invocation. The member function takes priority, so this test |
| // will only be true if there is not ALSO a format member. |
| template <typename T> |
| struct uses_format_provider |
| : public std::integral_constant< |
| bool, !uses_format_member<T>::value && has_FormatProvider<T>::value> { |
| }; |
| |
| // Simple template that decides whether a type T has neither a member-function |
| // nor format_provider based implementation that it can use. Mostly used so |
| // that the compiler spits out a nice diagnostic when a type with no format |
| // implementation can be located. |
| template <typename T> |
| struct uses_missing_provider |
| : public std::integral_constant<bool, |
| !uses_format_member<T>::value && |
| !uses_format_provider<T>::value> {}; |
| |
| template <typename T> |
| typename std::enable_if<uses_format_member<T>::value, T>::type |
| build_format_adapter(T &&Item) { |
| return std::forward<T>(Item); |
| } |
| |
| template <typename T> |
| typename std::enable_if<uses_format_provider<T>::value, |
| provider_format_adapter<T>>::type |
| build_format_adapter(T &&Item) { |
| return provider_format_adapter<T>(std::forward<T>(Item)); |
| } |
| |
| template <typename T> |
| typename std::enable_if<uses_missing_provider<T>::value, |
| missing_format_adapter<T>>::type |
| build_format_adapter(T &&Item) { |
| return missing_format_adapter<T>(); |
| } |
| } |
| } |
| |
| #endif |