最終更新日時(UTC): 2024年06月11日 13時45分38秒
Akira Takahashi が更新

履歴 編集

class template
<type_traits>

# std::is_trivially_destructible(C++11)

    namespace std {
      template <class T>
      struct is_trivially_destructible;

      template <class T>
      inline constexpr bool is_trivially_destructible_v
        = is_trivially_destructible<T>::value;          // C++17
    }

## 概要

型`T`がトリビアルに破棄可能か調べる。

## 要件

型`T`は完全型であるか、`const`/`volatile`修飾された(あるいはされていない)`void`か、要素数不明の配列型でなければならない。

## 効果

`is_trivially_destructible`は、`T`がトリビアルに破棄可能な型であるならば`true_type`から派生し、そうでなければ`false_type`から派生する。

「トリビアルに破棄可能」とは、ユーザー定義されないデストラクタを持っているということを意味する。

## 例

### 基本的な使用例

    #include <type_traits>

    struct C1 {
      // トリビアルなデストラクタを持っている

      // 特殊関数ではないメンバ関数は持っている
      int f(int x) const { return x; }
    };

    struct C2 {
      // 非トリビアルなデストラクタを持っている
      ~C2() {}
    };

    // 組み込み型は全てトリビアルに破棄可能
    static_assert(std::is_trivially_destructible<int>::value == true, "int is trivially destructible");
    static_assert(std::is_trivially_destructible<int*>::value == true, "int* is trivially destructible");

    // ユーザー定義型は、ユーザー定義のデストラクタを持っていなければトリビアルに破棄可能
    static_assert(std::is_trivially_destructible<C1>::value == true, "C1 is trivially destructible");
    static_assert(std::is_trivially_destructible<C2>::value == false, "C2 isn't trivially destructible");

    int main() {}

#### 出力

### 包含する型がデストラクタを呼び出す必要があるかないかで、デストラクタの定義を分ける (C++11)

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

    class TrivialBase {
    public:
      ~TrivialBase() = default;
    };

    class NonTrivialBase {
    public:
      ~NonTrivialBase() {
        std::cout << "destruct" << std::endl;
      }
    };

    template <class T>
    class A : public std::conditional<
                std::is_trivially_destructible<T>::value,
                TrivialBase,
                NonTrivialBase
              >::type {
      T x;
    };

    int main()
    {
      A<int> a;         // trivially destructible
      A<std::string> b; // non trivially destructible
    }

#### 出力

    destruct

### 包含する型がデストラクタを呼び出す必要があるかないかで、デストラクタの定義を分ける (C++20)

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

    template <class T>
    class A {
      T x;
    public:
      ~A() requires(!std::is_trivially_destructible_v<T>) {
        std::cout << "destruct" << std::endl;
      }

      ~A() = default;
    };

    int main()
    {
      A<int> a;         // trivially destructible
      A<std::string> b; // non trivially destructible
    }

#### 出力

    destruct

## バージョン

### 言語

- C++11

### 処理系

- Clang: 3.0 ✅
- GCC: 4.8.2 ✅
- Visual C++: 2012 ✅, 2013 ✅, 2015 ✅

#### 備考

- Clang 12.0時点では、コンセプトによるデストラクタのオーバーロードはサポートされておらず、コンパイルエラーになるか、もしくはオーバーロードしたデストラクタが動作しない。Bug 50570 - Clang either crashes or choose wrong destructor when using multiple destructors using C++20 constraints

## 関連項目

- `std::optional`のデストラクタ
- `std::variant`のデストラクタ
- `std::vector`のデストラクタ

## 参照

- P0006R0 Adopt Type Traits Variable Templates from Library Fundamentals TS for C++17
- An Example that Omits Destructor Calls For Types with Trivial Destructors
  - デストラクタを呼び出す必要のない型の配列に対して、デストラクタを呼び出すループを省略する最適化の例
- Multiple destructors with C++ concepts - Sandor Dargo's Blog