最終更新日時(UTC):
が更新

履歴 編集

class template
<type_traits>

std::is_literal_type(C++11)(C++17で非推奨)(C++20で削除)

namespace std {
  template <class T>
  struct is_literal_type;

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

この機能は、C++17から非推奨となり、C++20で削除された。

概要

Tがリテラル型か調べる。

要件

remove_all_extents<T>::typeは、完全型か、const/volatile修飾された(あるいはされていない)voidでなければならない。

効果

is_literal_typeは、型Tがリテラル型であるならばtrue_typeから派生し、そうでなければfalse_typeから派生する。

リテラル型とは、以下のいずれかの条件を満たす型である:

  • スカラ型
  • リテラル型への参照
  • リテラル型の配列
  • 以下の全ての特性を持つクラス型
    • トリビアルなデストラクタを持つ
    • 全てのコンストラクタが、定数式で初期化できること
    • 集成体であること、もしくはコピー/ムーブコンストラクタ以外のconstexprコンストラクタやconstexprコンストラクタテンプレートを一つ以上持っていること
    • 全てのメンバ変数および基底クラスがリテラル型であること
  • void (C++14から)

リテラル型は、constexpr関数のパラメータおよび戻り値の型に対する制約として使用されている。

非推奨・削除の詳細

この型特性は、ジェネリックコードにおいて特定の型がconstexprに振る舞えるかを判定する機能を持つが、ユーザー定義型の場合には「少なくとも一つ以上のconstexprコンストラクタを持つこと」という条件になっていた。しかし、いずれかのコンストラクタがconstexprで、それ以外がconstexprコンストラクタではなく、それに意味がある場合に、この型特性は使いにくかった。

実際に必要となるのは、特定の型がconstexprに振る舞えるかではなく、特定の構築処理で定数初期化ができるかであるため、リテラル型という考え方は廃止すべきである、という結論になった。

#include <type_traits>

struct X {
  int value;

  constexpr X(int value)
    : value(value) {}
};

static_assert(std::is_literal_type<int>::value, "int is literal type");
static_assert(std::is_literal_type<void>::value, "void is literal type");
static_assert(std::is_literal_type<X>::value, "X is literal type");

int main() {}

出力

バージョン

言語

  • C++11

処理系

  • Clang: 3.1
  • GCC: 4.6.4
  • Visual C++: 2012, 2013, 2015
    • 2012~2013は、C++11の定義に基づく実装となっている。すなわち、テンプレート実引数としてvoidを渡すとstd::false_typeからの派生になる。

備考

Clang 3.0では、上記サンプルにおけるX型が、リテラル型と見なされない。この問題は、Clang 3.1で修正されている。

参照