最終更新日時:
が更新

履歴 編集

concept
<memory>

std::tagging-compatible-pointee(C++29)

namespace std {
  template <class U, class PtrT, unsigned int BitsRequested,
            size_t Alignment = alignof(U)>
  concept tagging-compatible-pointee =  // 説明専用
    convertible_to<U*, PtrT> &&
    pointer_bits_available(Alignment) >= BitsRequested &&
    (is_void_v<element-of<PtrT>> ||
     is_scalar_v<element-of<PtrT>> ||
     is_union_v<element-of<PtrT>> ||
     is_pointer_interconvertible_base_of_v<element-of<PtrT>, U>);
}

概要

tagging-compatible-pointeeは、型Uのポインタが、PtrT型のポインタとしてBitsRequestedビットのタグ付けと互換であることを表す説明専用コンセプトである。

pointer_tag_pairコンストラクタfrom_overaligned()の制約として使用される。

要件

以下のすべてを満たすこと。

  • U*PtrTへ変換可能であること
  • pointer_bits_available(Alignment) >= BitsRequestedであること(アライメントから、要求したビット数を確保できること)
  • 指す先の型(説明専用のelement-of<PtrT>pointer_traits<PtrT>::element_type)が次のいずれかであること
    • void・スカラ型・共用体である
    • Uのポインタ相互変換可能 (pointer-interconvertible) な基底クラスである。これによって、仮想継承や先頭以外の基底クラスへのポインタなど、アドレス調整をともなうポインタ変換が除外される

#include <memory>

struct Base { int a; };
struct Derived : Base {};          // 追加のメンバがないため標準レイアウト
struct WithMember : Base { int b; };
struct Virt : virtual Base { int c; };

int main()
{
  Derived d{};
  WithMember w{};
  Virt v{};
  char c = 0;

  // OK : Derivedのアライメントは4なので、1ビットのタグを確保できる。
  //      BaseはDerivedのポインタ相互変換可能な基底クラスであり、
  //      Derived*からBase*への変換でアドレスは変わらない
  std::pointer_tag_pair<Base*, 1> p1{&d, 1u};

  // コンパイルエラー! WithMemberは基底クラスと派生クラスの両方にメンバを持ち、
  //                   標準レイアウトではないため、ポインタ相互変換可能ではない
  // std::pointer_tag_pair<Base*, 1> p2{&w, 1u};

  // コンパイルエラー! 仮想継承では、ポインタの変換にアドレスの調整をともなうため、
  //                   下位ビットのタグが保たれる保証がない
  // std::pointer_tag_pair<Base*, 1> p3{&v, 1u};

  // コンパイルエラー! charのアライメントは1なので、タグ用のビットを確保できない
  // std::pointer_tag_pair<char*, 1> p4{&c, 1u};
}

出力

バージョン

言語

  • C++29

処理系

関連項目

参照