C/C++ Arena

Step 3 of 9

Type traits

<type_traits> is a library of compile-time questions and answers about types. It has two kinds of tools:

Combined with if constexpr, a single template can handle each kind of type correctly:

#include <iostream>
#include <string>
#include <type_traits>

template <typename T>
std::string info(const T&) {
    std::string s;
    if constexpr (std::is_integral_v<T>) {
        s = std::is_signed_v<T> ? "signed int" : "unsigned int";
        s += " of " + std::to_string(sizeof(T) * 8) + " bits";
    } else if constexpr (std::is_floating_point_v<T>) {
        s = "floating point";
    } else if constexpr (std::is_same_v<T, std::string>) {
        s = "std::string";
    } else {
        s = "something else";
    }
    return s;
}

int main() {
    short a = 1;
    unsigned char b = 2;
    std::cout << info(a) << "\n" << info(b) << "\n" << info(2.5f) << "\n";
    std::cout << info(std::string("x")) << "\n" << info(nullptr) << "\n";
    static_assert(std::is_same_v<std::remove_cvref_t<const int&>, int>);
}
signed int of 16 bits
unsigned int of 8 bits
floating point
std::string
something else

Traps

decltype

decltype(expr) is the type of an expression, worked out at compile time without running it. If a is an int and b a double, decltype(a + b) is double. Generic code uses it to name types it can't spell out, like std::vector<decltype(a + b)>, and you can declare a variable with exactly another one's type: decltype(total) copy = 0;.

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.

Previous: Perfect forwarding Next: Writing your own trait