C++ Template Metaprogramming
Solutions to the exercises throughout the book
Loading...
Searching...
No Matches
c++20/exercise-2-4.hpp
Go to the documentation of this file.
1// ===-- chapter-2/c++20/exercise-2-4.hpp ----------------- -*- C++ -*- --=== //
9#ifndef EXERCISE_2_4
10#define EXERCISE_2_4
11
12#include <iostream>
13#include <string>
14
15
16namespace exercise_2_4 {
17
20inline namespace cpp20 {
21
40template <typename T> struct type_descriptor { };
41
51template <typename T> consteval T *error_unhandled_type() { return nullptr; }
52
53template <typename T>
54std::ostream& operator<<(std::ostream& os, type_descriptor<T> const&)
55{
57 // Non-leaf data-types:
59
60 if constexpr (std::is_const<T>::value) {
61 return os << type_descriptor<typename std::remove_const<T>::type>()
62 << " const";
63 } else if constexpr (std::is_lvalue_reference<T>::value) {
64 return os << type_descriptor<typename std::remove_reference<T>::type>()
65 << '&';
66 } else if constexpr (std::is_pointer<T>::value) {
67 using PointedT = typename std::remove_pointer<T>::type;
68 if constexpr (std::is_function<PointedT>::value) {
69 return os << type_descriptor<
70 typename std::invoke_result<PointedT>::type>()
71 << "(*)()";
72 } else {
73 return os << type_descriptor<PointedT>() << '*';
74 }
75 } else if constexpr (std::is_array<T>::value) {
76 if constexpr (std::is_bounded_array<T>::value) {
77 return os << type_descriptor<typename std::remove_extent<T>::type>()
78 << '[' << std::extent<T>::value << ']';
79 } else {
80 return os << type_descriptor<
81 typename std::remove_extent<T>::type>() << "[]";
82 }
83 } else if constexpr (std::is_function<T>::value) {
84 return os << type_descriptor<typename std::invoke_result<T>::type>()
85 << "()";
86 } else if constexpr (std::is_fundamental<T>::value) {
88 // Leaf data-types:
90
91 if constexpr (std::is_integral<T>::value) {
92 // NOTE: This "unsigned" is a three line change with if-constexpr,
93 // but with template specialization, it requires doubling the count
94 // of integral type specializations!
95 if constexpr (std::is_unsigned<T>::value) {
96 os << "unsigned ";
97 }
98
99 if constexpr (sizeof(T) == 1) { return os << "char"; }
100 else if constexpr (sizeof(T) == 2) { return os << "short int"; }
101 else if constexpr (sizeof(T) == 4) { return os << "int"; }
102 else if constexpr (sizeof(T) == 8) { return os << "long int"; }
103 else return error_unhandled_type<T>();
104 } else {
105 return error_unhandled_type<T>();
106 }
107 } else {
108 return error_unhandled_type<T>();
109 }
110}
111
112} // inline namespace cpp20
113} // namespace exercise_2_4
114
115#endif // EXERCISE_2_4
std::ostream & operator<<(std::ostream &os, type_descriptor< T > const &)
consteval T * error_unhandled_type()
Produce a compile-time failure for an "unhandled" type.
Encapsulate solution for Exercise 2-4.
Print (a limited set of) data-types.
Print (a limited set of) data-types.