C++ Template Metaprogramming
Solutions to the exercises throughout the book
Loading...
Searching...
No Matches
c++20/exercise-2-5.hpp
Go to the documentation of this file.
1// ===-- chapter-2/c++20/exercise-2-5.hpp ----------------- -*- C++ -*- --=== //
9#ifndef EXERCISE_2_5
10#define EXERCISE_2_5
11
12#include <iostream>
13
14
15#ifndef EXERCISE_2_4
16namespace exercise_2_4 {
19template <typename T> consteval T *error_unhandled_type() { return nullptr; }
20} // namespace exercise_2_4
21#endif
22
23namespace exercise_2_5 {
24
27inline namespace cpp20 {
28
33template <typename T> struct type_descriptor_eng { };
34
35template <typename T>
36std::ostream& operator<<(std::ostream& os, type_descriptor_eng<T> const&)
37{
39 // Non-leaf data-types:
41
42 if constexpr (std::is_const<T>::value) {
43 return os << "const "
45 } else if constexpr (std::is_lvalue_reference<T>::value) {
46 return os << "reference to "
48 typename std::remove_reference<T>::type>();
49 } else if constexpr (std::is_pointer<T>::value) {
50 using PointedT = typename std::remove_pointer<T>::type;
51 if constexpr (std::is_function<PointedT>::value) {
52 return os << "pointer to function returning "
54 typename std::invoke_result<PointedT>::type>();
55 } else {
56 return os << "pointer to " << type_descriptor_eng<PointedT>();
57 }
58 } else if constexpr (std::is_array<T>::value) {
59 if constexpr (std::is_bounded_array<T>::value) {
60 os << std::extent<T>::value << " element ";
61 }
62
63 return os << "array of "
65 typename std::remove_extent<T>::type>();
66 } else if constexpr (std::is_function<T>::value) {
67 return os << "function returning "
69 typename std::invoke_result<T>::type>();
70 } else if constexpr (std::is_fundamental<T>::value) {
72 // Leaf data-types:
74
75 if constexpr (std::is_integral<T>::value) {
76 // NOTE: This "unsigned" is a three line change with if-constexpr,
77 // but with template specialization, it requires doubling the count
78 // of integral type specializations!
79 if constexpr (std::is_unsigned<T>::value) {
80 os << "unsigned ";
81 }
82
83 if constexpr (sizeof(T) == 1) { return os << "char"; }
84 else if constexpr (sizeof(T) == 2) { return os << "short int"; }
85 else if constexpr (sizeof(T) == 4) { return os << "int"; }
86 else if constexpr (sizeof(T) == 8) { return os << "long int"; }
87 else return exercise_2_4::error_unhandled_type<T>();
88 } else {
89 return exercise_2_4::error_unhandled_type<T>();
90 }
91 } else {
92 return exercise_2_4::error_unhandled_type<T>();
93 }
94}
95
96} // inline namespace cpp20
97} // namespace exercise_2_4
98
99#endif // EXERCISE_2_5
consteval T * error_unhandled_type()
Produce a compile-time failure for an "unhandled" type.
Encapsulate solution for Exercise 2-4.
std::ostream & operator<<(std::ostream &os, type_descriptor_eng< T > const &)
Encapsulate solution for Exercise 2-5.
Display data-types in English wording.
Display data-types in English wording.