• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

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

    履歴 編集

    class template
    <type_traits>

    std::is_literal_type

    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で修正されている。

    参照