1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <stddef.h> 8 #include <utility> 9 10 // 11 // Compile-time type info utility without RTTI. 12 // 13 14 // Check for supported versions of Clang or GCC. 15 #if defined(__clang__) 16 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30600 17 #error "Unsupported clang version!" 18 #endif 19 #elif defined(__GNUC__) 20 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 50400 21 #error "Unsupported gcc version!" 22 #endif 23 #else 24 #error "Unrecognized compiler!" 25 #endif 26 27 namespace fbl { 28 29 // TypeInfo provides a compile-time string name for the given type T without 30 // requiring RTTI to be enabled. The type string is derived from 31 // __PRETTY_FUNCTION__ using a constexpr expression that works with both GCC and 32 // Clang. 33 // 34 // TypeInfo may be used in a wide variety of contexts. Here is one example of 35 // logging the types used to invoke a template function: 36 // 37 // template <typename T, typename U, typename V> 38 // void Function(const T& t, const U& u, const V& v) { 39 // log("Function<%s, %s, %s>(...) invoked!", TypeInfo<T>::Name(), 40 // TypeInfo<U>::Name(), TypeInfo<V>::Name()); 41 // // Function body... 42 // } 43 // 44 template <typename T> 45 class TypeInfo { 46 public: 47 // Returns the string name for type T. Name()48 static const char* Name() { 49 static constexpr TypeInfo type_info; 50 return type_info.name; 51 } 52 53 private: 54 struct Info { 55 const char* const kName; 56 const size_t kOffset; 57 const size_t kSize; 58 }; 59 Get()60 static constexpr Info Get() { 61 const char* type_name = __PRETTY_FUNCTION__; 62 const size_t size = sizeof(__PRETTY_FUNCTION__); 63 size_t start = Find(type_name, '=', 0, Forward) + 2; 64 size_t end = Find(type_name, ']', size - 1, Reverse) + 1; 65 return {type_name, start, end - start}; 66 } 67 68 enum Direction { Forward, 69 Reverse }; Find(const char * subject,char value,size_t index,Direction direction)70 static constexpr size_t Find(const char* subject, char value, size_t index, 71 Direction direction) { 72 while (subject[index] != value) 73 index += direction == Forward ? 1 : -1; 74 return index; 75 } 76 77 static constexpr size_t Size = Get().kSize; 78 static constexpr size_t Offset = Get().kOffset; 79 static constexpr const char* BaseName = Get().kName; 80 TypeInfo()81 constexpr TypeInfo() 82 : TypeInfo(std::make_index_sequence<Size>{}) {} 83 template <size_t... Is> TypeInfo(std::index_sequence<Is...>)84 constexpr TypeInfo(std::index_sequence<Is...>) 85 : name{(Is < Size - 1 ? BaseName[Offset + Is] : '\0')...} {} 86 87 const char name[Size]; 88 }; 89 90 } // namespace fbl 91