FormatVariadicDetails.h revision 341825
1168457Skato//===- FormatVariadicDetails.h - Helpers for FormatVariadic.h ----*- C++-*-===// 264123Skato// 364123Skato// The LLVM Compiler Infrastructure 464123Skato// 564123Skato// This file is distributed under the University of Illinois Open Source 664123Skato// License. See LICENSE.TXT for details. 764123Skato// 864123Skato//===----------------------------------------------------------------------===// 964123Skato 1064123Skato#ifndef LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H 1164123Skato#define LLVM_SUPPORT_FORMATVARIADIC_DETAILS_H 1264123Skato 1364123Skato#include "llvm/ADT/StringRef.h" 1464123Skato#include "llvm/Support/raw_ostream.h" 1564123Skato 1664123Skato#include <type_traits> 1764123Skato 1864123Skatonamespace llvm { 1964123Skatotemplate <typename T, typename Enable = void> struct format_provider {}; 2064123Skatoclass Error; 2164123Skato 2264123Skatonamespace detail { 2364123Skatoclass format_adapter { 2464123Skatoprotected: 2564123Skato virtual ~format_adapter() {} 2664123Skato 2764123Skatopublic: 2864123Skato virtual void format(raw_ostream &S, StringRef Options) = 0; 2964123Skato}; 3064123Skato 3164123Skatotemplate <typename T> class provider_format_adapter : public format_adapter { 3264123Skato T Item; 3364123Skato 3464123Skatopublic: 3564123Skato explicit provider_format_adapter(T &&Item) : Item(std::forward<T>(Item)) {} 3664123Skato 3764123Skato void format(llvm::raw_ostream &S, StringRef Options) override { 3864123Skato format_provider<typename std::decay<T>::type>::format(Item, S, Options); 3964123Skato } 4064123Skato}; 4164123Skato 4264123Skatotemplate <typename T> 4364123Skatoclass stream_operator_format_adapter : public format_adapter { 4464123Skato T Item; 4564123Skato 4664123Skatopublic: 4764123Skato explicit stream_operator_format_adapter(T &&Item) 4864123Skato : Item(std::forward<T>(Item)) {} 4964123Skato 5064123Skato void format(llvm::raw_ostream &S, StringRef Options) override { S << Item; } 5164123Skato}; 5264123Skato 5364123Skatotemplate <typename T> class missing_format_adapter; 5464123Skato 5564123Skato// Test if format_provider<T> is defined on T and contains a member function 5664123Skato// with the signature: 5764123Skato// static void format(const T&, raw_stream &, StringRef); 5864123Skato// 5964123Skatotemplate <class T> class has_FormatProvider { 6064123Skatopublic: 6164123Skato using Decayed = typename std::decay<T>::type; 6264123Skato typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &, 63167657Skato StringRef); 6464123Skato 6564123Skato template <typename U> 6664123Skato static char test(SameType<Signature_format, &U::format> *); 6764123Skato 6864123Skato template <typename U> static double test(...); 6964123Skato 7064123Skato static bool const value = 7164123Skato (sizeof(test<llvm::format_provider<Decayed>>(nullptr)) == 1); 7264123Skato}; 7364123Skato 7464123Skato// Test if raw_ostream& << T -> raw_ostream& is findable via ADL. 7564123Skatotemplate <class T> class has_StreamOperator { 7664123Skatopublic: 7764123Skato using ConstRefT = const typename std::decay<T>::type &; 7864123Skato 7964123Skato template <typename U> 8064123Skato static char test(typename std::enable_if< 8164123Skato std::is_same<decltype(std::declval<llvm::raw_ostream &>() 8264123Skato << std::declval<U>()), 8364123Skato llvm::raw_ostream &>::value, 8464123Skato int *>::type); 8564123Skato 8664123Skato template <typename U> static double test(...); 8764123Skato 8864123Skato static bool const value = (sizeof(test<ConstRefT>(nullptr)) == 1); 8964123Skato}; 9064123Skato 9164123Skato// Simple template that decides whether a type T should use the member-function 9264123Skato// based format() invocation. 9364123Skatotemplate <typename T> 9464123Skatostruct uses_format_member 9564123Skato : public std::integral_constant< 9664123Skato bool, 9764123Skato std::is_base_of<format_adapter, 9864123Skato typename std::remove_reference<T>::type>::value> {}; 9964123Skato 10064123Skato// Simple template that decides whether a type T should use the format_provider 10164123Skato// based format() invocation. The member function takes priority, so this test 10264123Skato// will only be true if there is not ALSO a format member. 10364123Skatotemplate <typename T> 10464123Skatostruct uses_format_provider 10564123Skato : public std::integral_constant< 10664123Skato bool, !uses_format_member<T>::value && has_FormatProvider<T>::value> { 10764123Skato}; 10864123Skato 10964123Skato// Simple template that decides whether a type T should use the operator<< 11064123Skato// based format() invocation. This takes last priority. 11164123Skatotemplate <typename T> 11264123Skatostruct uses_stream_operator 11364123Skato : public std::integral_constant<bool, !uses_format_member<T>::value && 11464123Skato !uses_format_provider<T>::value && 11564123Skato has_StreamOperator<T>::value> {}; 11664123Skato 11764123Skato// Simple template that decides whether a type T has neither a member-function 11864123Skato// nor format_provider based implementation that it can use. Mostly used so 11964123Skato// that the compiler spits out a nice diagnostic when a type with no format 12064123Skato// implementation can be located. 12164123Skatotemplate <typename T> 12264123Skatostruct uses_missing_provider 12364123Skato : public std::integral_constant<bool, !uses_format_member<T>::value && 12464123Skato !uses_format_provider<T>::value && 12564123Skato !uses_stream_operator<T>::value> { 12664123Skato}; 12764123Skato 12864295Skatotemplate <typename T> 12964123Skatotypename std::enable_if<uses_format_member<T>::value, T>::type 13064123Skatobuild_format_adapter(T &&Item) { 13164123Skato return std::forward<T>(Item); 13264123Skato} 13364123Skato 13464123Skatotemplate <typename T> 13564123Skatotypename std::enable_if<uses_format_provider<T>::value, 13664123Skato provider_format_adapter<T>>::type 13764123Skatobuild_format_adapter(T &&Item) { 13864123Skato return provider_format_adapter<T>(std::forward<T>(Item)); 13964123Skato} 14064123Skato 14164123Skatotemplate <typename T> 14264123Skatotypename std::enable_if<uses_stream_operator<T>::value, 14364123Skato stream_operator_format_adapter<T>>::type 14464123Skatobuild_format_adapter(T &&Item) { 14564123Skato // If the caller passed an Error by value, then stream_operator_format_adapter 14664123Skato // would be responsible for consuming it. 14764123Skato // Make the caller opt into this by calling fmt_consume(). 14864123Skato static_assert( 14964123Skato !std::is_same<llvm::Error, typename std::remove_cv<T>::type>::value, 15064123Skato "llvm::Error-by-value must be wrapped in fmt_consume() for formatv"); 15164123Skato return stream_operator_format_adapter<T>(std::forward<T>(Item)); 15264123Skato} 15364123Skato 15464123Skatotemplate <typename T> 15564123Skatotypename std::enable_if<uses_missing_provider<T>::value, 15664123Skato missing_format_adapter<T>>::type 15764123Skatobuild_format_adapter(T &&Item) { 15864123Skato return missing_format_adapter<T>(); 15964123Skato} 16064123Skato} 16164123Skato} 16264123Skato 16364123Skato#endif 16464123Skato