C++ <type_traits>
应用详解 <type_traits>
是 C++ 标准库中的一个头文件,提供了编译时类型检查、类型转换和类型特性查询 的工具。它广泛应用于模板元编程(Template Metaprogramming)、SFINAE(Substitution Failure Is Not An Error)、类型推导优化等场景。
1. <type_traits>
的核心作用 <type_traits>
主要提供以下功能:
类型检查 (Type Traits):判断类型是否满足某些条件(如 is_integral
、is_pointer
)。类型转换 (Type Transformations):修改类型(如 remove_pointer
、add_const
)。SFINAE 辅助 :用于模板特化或重载决议。编译时逻辑控制 :结合 if constexpr
或 static_assert
进行条件编译。
2. 常用类型检查(Type Traits) 2.1 基本类型检查
特性 作用 示例 std::is_void<T>
检查 T
是否是 void
is_void<void>::value
→ true
std::is_integral<T>
检查 T
是否是整数类型 is_integral<int>::value
→ true
std::is_floating_point<T>
检查 T
是否是浮点类型 is_floating_point<float>::value
→ true
std::is_array<T>
检查 T
是否是数组 is_array<int[3]>::value
→ true
std::is_pointer<T>
检查 T
是否是指针 is_pointer<int*>::value
→ true
std::is_reference<T>
检查 T
是否是引用 is_reference<int&>::value
→ true
std::is_const<T>
检查 T
是否是 const
修饰 is_const<const int>::value
→ true
std::is_volatile<T>
检查 T
是否是 volatile
修饰 is_volatile<volatile int>::value
→ true
std::is_same<T, U>
检查 T
和 U
是否相同 is_same<int, int32_t>::value
→ true
(依赖平台)
示例:检查类型是否为整数 #include <iostream>
#include <type_traits>
template<typename T>
void check_integral() {
if constexpr (std::is_integral_v<T>) { // C++17 起支持 _v 后缀
std::cout << "T is integral type." << std::endl;
} else {
std::cout << "T is NOT integral type." << std::endl;
}
}
int main() {
check_integral<int>(); // 输出: T is integral type.
check_integral<float>(); // 输出: T is NOT integral type.
return 0;
}
2.2 复合类型检查
特性 作用 示例 std::is_class<T>
检查 T
是否是类类型 is_class<std::string>::value
→ true
std::is_union<T>
检查 T
是否是联合体 is_union<union{}>::value
→ true
std::is_enum<T>
检查 T
是否是枚举 enum E { A }; is_enum<E>::value
→ true
std::is_function<T>
检查 T
是否是函数 is_function<void()>::value
→ true
std::is_member_pointer<T>
检查 T
是否是成员指针 is_member_pointer<int MyClass::*>::value
→ true
示例:检查类型是否为类 #include <iostream>
#include <type_traits>
struct MyClass {};
template<typename T>
void check_class() {
if constexpr (std::is_class_v<T>) {
std::cout << "T is a class." << std::endl;
} else {
std::cout << "T is NOT a class." << std::endl;
}
}
int main() {
check_class<MyClass>(); // 输出: T is a class.
check_class<int>(); // 输出: T is NOT a class.
return 0;
}
3. 类型转换(Type Transformations) <type_traits>
提供了一些编译时类型修改 的工具:
特性 作用 示例 std::remove_const<T>
移除 const
修饰 remove_const<const int>::type
→ int
std::remove_volatile<T>
移除 volatile
修饰 remove_volatile<volatile int>::type
→ int
std::remove_cv<T>
移除 const
和 volatile
remove_cv<const volatile int>::type
→ int
std::remove_pointer<T>
移除指针 remove_pointer<int*>::type
→ int
std::remove_reference<T>
移除引用 remove_reference<int&>::type
→ int
std::add_const<T>
添加 const
修饰 add_const<int>::type
→ const int
std::add_volatile<T>
添加 volatile
修饰 add_volatile<int>::type
→ volatile int
std::add_pointer<T>
添加指针 add_pointer<int>::type
→ int*
std::add_lvalue_reference<T>
添加左值引用 add_lvalue_reference<int>::type
→ int&
std::add_rvalue_reference<T>
添加右值引用 add_rvalue_reference<int>::type
→ int&&
std::decay<T>
模拟值传递(移除引用、const
、数组/函数转指针) decay<int&>::type
→ int
示例:移除 const
和引用 #include <iostream>
#include <type_traits>
int main() {
using T1 = const int&;
using T2 = std::remove_const_t<std::remove_reference_t<T1>>; // C++14 起支持 _t 后缀
std::cout << std::is_same_v<T2, int> << std::endl; // 输出: 1 (true)
return 0;
}
4. SFINAE 应用 SFINAE(Substitution Failure Is Not An Error)是一种模板特化技巧 ,结合 <type_traits>
可以实现编译时分支选择 。
4.1 基本 SFINAE 示例 #include <iostream>
#include <type_traits>
// 仅当 T 是整数类型时启用
template<typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
void process_integral(T value) {
std::cout << "Processing integral: " << value << std::endl;
}
// 仅当 T 是浮点类型时启用
template<typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
void process_floating(T value) {
std::cout << "Processing floating: " << value << std::endl;
}
int main() {
process_integral(42); // 输出: Processing integral: 42
process_floating(3.14); // 输出: Processing floating: 3.14
// process_integral(3.14); // 编译错误: no matching function
return 0;
}
4.2 更复杂的 SFINAE #include <iostream>
#include <type_traits>
// 如果 T 是指针,返回 true
template<typename T>
auto is_pointer_v = std::is_pointer_v<T>;
// SFINAE 示例:仅当 T 不是指针时启用
template<typename T, typename = std::enable_if_t<!is_pointer_v<T>>>
void foo(T value) {
std::cout << "Non-pointer: " << value << std::endl;
}
int main() {
foo(42); // 输出: Non-pointer: 42
// foo(nullptr); // 编译错误: no matching function
return 0;
}
5. C++17 改进:if constexpr
C++17 引入了 if constexpr
,可以替代部分 SFINAE 用法,使代码更简洁:
#include <iostream>
#include <type_traits>
template<typename T>
void check_type(T value) {
if constexpr (std::is_integral_v<T>) {
std::cout << "Integral: " << value << std::endl;
} else if constexpr (std::is_floating_point_v<T>) {
std::cout << "Floating: " << value << std::endl;
} else {
std::cout << "Unknown type" << std::endl;
}
}
int main() {
check_type(42); // 输出: Integral: 42
check_type(3.14); // 输出: Floating: 3.14
check_type("hello"); // 输出: Unknown type
return 0;
}
6. 总结
功能 示例 类型检查 is_integral<T>
, is_pointer<T>
类型转换 remove_const<T>
, add_pointer<T>
SFINAE enable_if_t<condition>
C++17 简化 if constexpr
<type_traits>
是 C++ 模板元编程的核心工具,广泛应用于:
编译时类型检查 (如 static_assert
)。模板特化 (SFINAE)。优化类型推导 (如 std::decay
)。C++17 后结合 if constexpr
简化代码 。掌握 <type_traits>
可以写出更高效、更灵活的模板代码!