Step 3 of 6
Type traits
<type_traits> answers questions about types at compile time: std::is_integral_v<T>, std::is_floating_point_v<T>, std::is_same_v<A, B>, std::is_pointer_v<T>... and transforms types: std::remove_cvref_t<T>, std::make_unsigned_t<T>.
Combined with if constexpr (from the templates module), a single template can handle each kind of type correctly:
template <typename T>
std::string describe(const T& v) {
if constexpr (std::is_integral_v<T>) return "int " + std::to_string(v);
else if constexpr (std::is_floating_point_v<T>) return "float";
else return "other";
}
Your turn: write template <typename T> std::string kind_of(const T&) returning "bool" for bool (careful: bool is an integral type, so check it first), "signed" or "unsigned" for other integral types, "float" for floating point, "pointer" for pointers, and "other" otherwise.