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