std::is_trivial (header <type_traits>) kiểm tra xem một kiểu T có phải là kiểu trivia (trivial type) hay không. Kiểu trivia là kiểu có thể sao chép bitwise (memcpy), khởi tạo tĩnh (static initialization), và không có logic phức tạp trong constructor/destructor/assignment.
Điều kiện để là Trivial Class
- Không có hàm ảo (virtual function) và không có lớp cơ sở ảo (virtual base class).
- Không có thành viên dữ liệu non-static có kiểu non-trivial.
- Không có lớp cơ sở non-trivial.
- Constructor mặc định, copy/move constructor, copy/move assignment, destructor đều là trivial (do compiler tự tạo).
- Không có initializer cho non-static data member (C++11:
int x = 0;làm class non-trivial).
Cú pháp
template <class T> struct is_trivial;
Ví dụ kiểm tra
#include <iostream>
#include <type_traits>
using namespace std;
class TP_1 { }; // Trivial: rỗng, compiler tạo tất cả trivial
class TP_2 { TP_2() {} }; // Non-trivial: user-defined constructor
class TP_3 : TP_2 { }; // Non-trivial: kế thừa từ non-trivial
class TP_4 { virtual void f(); }; // Non-trivial: có virtual function
class TrivialStruct {
int a;
double b;
}; // Trivial: chỉ có POD members
class NonTrivialStruct {
int a;
string s; // string non-trivial
}; // Non-trivial
int main() {
cout << boolalpha;
cout << "TP_1 (rỗng): " << is_trivial<TP_1>::value << '\n'; // true
cout << "TP_2 (user ctor): " << is_trivial<TP_2>::value << '\n'; // false
cout << "TP_3 (kế thừa TP_2): " << is_trivial<TP_3>::value << '\n'; // false
cout << "TP_4 (virtual): " << is_trivial<TP_4>::value << '\n'; // false
cout << "TrivialStruct: " << is_trivial<TrivialStruct>::value << '\n'; // true
cout << "NonTrivialStruct: " << is_trivial<NonTrivialStruct>::value << '\n'; // false
cout << "int: " << is_trivial<int>::value << '\n'; // true
cout << "int[10]: " << is_trivial<int[10]>::value << '\n'; // true
return 0;
}
Đầu ra
TP_1 (rỗng): true TP_2 (user ctor): false TP_3 (kế thừa TP_2): false TP_4 (virtual): false TrivialStruct: true NonTrivialStruct: false int: true int[10]: true
Mối quan hệ với type traits khác
is_trivial ≡ is_trivially_copyable && is_trivially_default_constructible
Trong đó:
is_trivially_copyable: có thể copy bằng memcpy (bitwise copy).is_trivially_default_constructible: default constructor là trivial.
Ứng dụng thực tế
- Tối ưu hóa memcpy: Nếu
is_trivial_v<T>true, có thể dùngmemcpythay vì copy từng phần tử. - Union an toàn: Chỉ các kiểu trivial được phép làm thành viên của union (C++11 cho phép non-trivial nhưng cần quản lý thủ công).
- Static initialization: Trivial type đảm bảo zero-initialization trước dynamic initialization.
- C ABI compatibility: Truyền qua biên giới C/C++ an toàn.
Lưu ý C++20
std::is_trivial bị deprecated cho một số trường hợp, khuyến nghị dùng tổ hợp is_trivially_copyable + is_trivially_default_constructible + is_trivially_destructible.