Type Traits Quick Reference
C++ type traits cheatsheet — primary type categories, type relationships, modifications, composite traits, and common patterns.
Primary Type Categories
cpp
#include <type_traits>
// is_X<T>::value or is_X_v<T> (C++17)
std::is_void_v<void> // true
std::is_integral_v<int> // true: int, bool, char, short, long...
std::is_floating_point_v<float> // true: float, double, long double
std::is_array_v<int[5]> // true
std::is_pointer_v<int*> // true
std::is_reference_v<int&> // true: lvalue or rvalue reference
std::is_lvalue_reference_v<int&> // true
std::is_rvalue_reference_v<int&&>// true
std::is_function_v<int(int)> // true (function types, not pointers)
std::is_enum_v<Color> // true
std::is_class_v<std::string> // true (struct and class)
std::is_union_v<U> // true (unions)
std::is_null_pointer_v<nullptr_t>// trueComposite Type Categories
cpp
std::is_arithmetic_v<int> // true: integral || floating_point
std::is_fundamental_v<int> // true: arithmetic || void || nullptr_t
std::is_scalar_v<int*> // true: arithmetic || pointer || enum || nullptr_t
std::is_object_v<int> // true: not function, reference, or void
std::is_compound_v<std::string> // true: not fundamental
std::is_member_pointer_v<int S::*>// true: member pointer typesType Properties
cpp
// const/volatile
std::is_const_v<const int> // true
std::is_volatile_v<volatile int> // true
// Special member functions
std::is_default_constructible_v<T>
std::is_copy_constructible_v<T>
std::is_move_constructible_v<T>
std::is_copy_assignable_v<T>
std::is_move_assignable_v<T>
std::is_destructible_v<T>
// Nothrow variants
std::is_nothrow_move_constructible_v<T>
std::is_nothrow_destructible_v<T>
// Triviality (important for memcpy eligibility)
std::is_trivially_copyable_v<T> // safe to memcpy
std::is_trivially_destructible_v<T> // dtor does nothing
std::is_trivial_v<T> // trivially default constructible + trivially copyable
std::is_standard_layout_v<T> // predictable layout (no virtual, single access)
std::is_pod_v<T> // trivial + standard layout (deprecated C++20)
// Misc
std::is_empty_v<T> // no data members, no virtual
std::is_abstract_v<T> // has pure virtual
std::is_polymorphic_v<T> // has any virtual
std::is_aggregate_v<T> // C++17: aggregate init eligible
std::is_signed_v<int> // true
std::is_unsigned_v<unsigned> // trueType Relationships
cpp
std::is_same_v<int, int> // true
std::is_same_v<int, long> // false (even if same size)
std::is_base_of_v<Base, Derived> // true
std::is_convertible_v<int, double> // true (implicit conversion exists)
std::is_nothrow_convertible_v<T, U> // C++20
// C++20
std::is_pointer_interconvertible_with_class_v<Struct, Member>
std::is_corresponding_member_v<S1, S2, Member1, Member2>Type Modifications
cpp
// Add/remove const-volatile
std::remove_const_t<const int> // int
std::remove_volatile_t<volatile int> // int
std::remove_cv_t<const volatile int> // int
std::add_const_t<int> // const int
std::add_volatile_t<int> // volatile int
// References
std::remove_reference_t<int&> // int
std::remove_reference_t<int&&> // int
std::add_lvalue_reference_t<int> // int&
std::add_rvalue_reference_t<int> // int&&
// Pointers
std::remove_pointer_t<int*> // int
std::add_pointer_t<int> // int*
// Arrays
std::remove_extent_t<int[5]> // int
std::remove_all_extents_t<int[3][4]> // int
std::rank_v<int[3][4]> // 2
std::extent_v<int[3][4], 0> // 3
std::extent_v<int[3][4], 1> // 4
// Combine cv + ref removal
std::remove_cvref_t<const int&> // int (C++20)
std::decay_t<const int&> // int (also decays arrays/functions to pointers)Utility Traits
cpp
// Conditional type selection
std::conditional_t<true, int, double> // int
std::conditional_t<false, int, double> // double
// Enable/disable overloads (pre-C++20)
template<typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
void f(T x);
// Identity
std::type_identity_t<int> // int (prevents deduction)
// Make signed/unsigned
std::make_signed_t<unsigned int> // int
std::make_unsigned_t<int> // unsigned int
// Common type (result of ternary operator)
std::common_type_t<int, double> // double
std::common_type_t<int, long> // long
// Underlying enum type
std::underlying_type_t<Color> // e.g. intSFINAE and Concepts Patterns
cpp
// C++17 SFINAE: enable_if
template<typename T>
std::enable_if_t<std::is_integral_v<T>, T>
safe_divide(T a, T b) { return b ? a/b : 0; }
// C++17: if constexpr (cleaner)
template<typename T>
auto process(T x) {
if constexpr (std::is_integral_v<T>) return x * 2;
else return x + 1.0;
}
// C++20: concepts (best)
template<std::integral T>
T safe_divide(T a, T b) { return b ? a/b : 0; }
// void_t for detecting member existence (C++17)
template<typename, typename = void>
struct has_size : std::false_type {};
template<typename T>
struct has_size<T, std::void_t<decltype(std::declval<T>().size())>>
: std::true_type {};
// C++20 requires (better)
template<typename T>
concept HasSize = requires(T t) { t.size(); };Common Patterns Summary
cpp
// "Is T a numeric type?"
template<typename T>
constexpr bool is_numeric = std::is_arithmetic_v<T> && !std::is_same_v<T, bool>;
// "Strip all qualifiers from T"
template<typename T>
using bare_t = std::remove_cvref_t<T>;
// "Is T a container (has begin/end)?"
template<typename T, typename = void>
inline constexpr bool is_range = false;
template<typename T>
inline constexpr bool is_range<T, std::void_t<
decltype(std::begin(std::declval<T&>())),
decltype(std::end(std::declval<T&>()))
>> = true;