FormatVariadicDetails.h revision 311116
1311116Sdim//===- FormatVariadicDetails.h - Helpers for FormatVariadic.h ----*- C++-*-===// 2311116Sdim// 3311116Sdim// The LLVM Compiler Infrastructure 4311116Sdim// 5311116Sdim// This file is distributed under the University of Illinois Open Source 6311116Sdim// License. See LICENSE.TXT for details. 7311116Sdim// 8311116Sdim//===----------------------------------------------------------------------===// 9311116Sdim 10311116Sdim#ifndef LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H 11311116Sdim#define LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H 12311116Sdim 13311116Sdim#include "llvm/ADT/StringRef.h" 14311116Sdim#include "llvm/Support/raw_ostream.h" 15311116Sdim 16311116Sdim#include <type_traits> 17311116Sdim 18311116Sdimnamespace llvm { 19311116Sdimtemplate <typename T, typename Enable = void> struct format_provider {}; 20311116Sdim 21311116Sdimnamespace detail { 22311116Sdimclass format_adapter { 23311116Sdimprotected: 24311116Sdim virtual ~format_adapter() {} 25311116Sdim 26311116Sdimpublic: 27311116Sdim virtual void format(raw_ostream &S, StringRef Options) = 0; 28311116Sdim}; 29311116Sdim 30311116Sdimtemplate <typename T> class provider_format_adapter : public format_adapter { 31311116Sdim T Item; 32311116Sdim 33311116Sdimpublic: 34311116Sdim explicit provider_format_adapter(T &&Item) : Item(Item) {} 35311116Sdim 36311116Sdim void format(llvm::raw_ostream &S, StringRef Options) override { 37311116Sdim format_provider<typename std::decay<T>::type>::format(Item, S, Options); 38311116Sdim } 39311116Sdim}; 40311116Sdim 41311116Sdimtemplate <typename T> class missing_format_adapter; 42311116Sdim 43311116Sdim// Test if format_provider<T> is defined on T and contains a member function 44311116Sdim// with the signature: 45311116Sdim// static void format(const T&, raw_stream &, StringRef); 46311116Sdim// 47311116Sdimtemplate <class T> class has_FormatProvider { 48311116Sdimpublic: 49311116Sdim using Decayed = typename std::decay<T>::type; 50311116Sdim typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &, 51311116Sdim StringRef); 52311116Sdim 53311116Sdim template <typename U> 54311116Sdim static char test(SameType<Signature_format, &U::format> *); 55311116Sdim 56311116Sdim template <typename U> static double test(...); 57311116Sdim 58311116Sdim static bool const value = 59311116Sdim (sizeof(test<llvm::format_provider<Decayed>>(nullptr)) == 1); 60311116Sdim}; 61311116Sdim 62311116Sdim// Simple template that decides whether a type T should use the member-function 63311116Sdim// based format() invocation. 64311116Sdimtemplate <typename T> 65311116Sdimstruct uses_format_member 66311116Sdim : public std::integral_constant< 67311116Sdim bool, 68311116Sdim std::is_base_of<format_adapter, 69311116Sdim typename std::remove_reference<T>::type>::value> {}; 70311116Sdim 71311116Sdim// Simple template that decides whether a type T should use the format_provider 72311116Sdim// based format() invocation. The member function takes priority, so this test 73311116Sdim// will only be true if there is not ALSO a format member. 74311116Sdimtemplate <typename T> 75311116Sdimstruct uses_format_provider 76311116Sdim : public std::integral_constant< 77311116Sdim bool, !uses_format_member<T>::value && has_FormatProvider<T>::value> { 78311116Sdim}; 79311116Sdim 80311116Sdim// Simple template that decides whether a type T has neither a member-function 81311116Sdim// nor format_provider based implementation that it can use. Mostly used so 82311116Sdim// that the compiler spits out a nice diagnostic when a type with no format 83311116Sdim// implementation can be located. 84311116Sdimtemplate <typename T> 85311116Sdimstruct uses_missing_provider 86311116Sdim : public std::integral_constant<bool, 87311116Sdim !uses_format_member<T>::value && 88311116Sdim !uses_format_provider<T>::value> {}; 89311116Sdim 90311116Sdimtemplate <typename T> 91311116Sdimtypename std::enable_if<uses_format_member<T>::value, T>::type 92311116Sdimbuild_format_adapter(T &&Item) { 93311116Sdim return std::forward<T>(Item); 94311116Sdim} 95311116Sdim 96311116Sdimtemplate <typename T> 97311116Sdimtypename std::enable_if<uses_format_provider<T>::value, 98311116Sdim provider_format_adapter<T>>::type 99311116Sdimbuild_format_adapter(T &&Item) { 100311116Sdim return provider_format_adapter<T>(std::forward<T>(Item)); 101311116Sdim} 102311116Sdim 103311116Sdimtemplate <typename T> 104311116Sdimtypename std::enable_if<uses_missing_provider<T>::value, 105311116Sdim missing_format_adapter<T>>::type 106311116Sdimbuild_format_adapter(T &&Item) { 107311116Sdim return missing_format_adapter<T>(); 108311116Sdim} 109311116Sdim} 110311116Sdim} 111311116Sdim 112311116Sdim#endif 113