Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Template is_trivial trong C++ STL

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ùng memcpy thay 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.