最終更新日時:
が更新

履歴 編集

function
<regex>

std::match_results::get_allocator(C++11)

allocator_type get_allocator() const;

概要

アロケータオブジェクトのコピーを取得する。

戻り値

*this で使用しているアロケータオブジェクトのコピー

備考

*this で使用しているアロケータオブジェクトは、構築時に設定されたものか、直近の代入時、あるいは、交換時に設定されたもののいずれかである。

#include <iostream>
#include <memory>
#include <regex>
#include <type_traits>

template <class T>
struct my_alloc {
  using value_type = T;
  T* allocate(std::size_t n) { return static_cast<T*>(::operator new(sizeof(T) * n)); }
  void deallocate(T* p, std::size_t) noexcept { ::operator delete(static_cast<void*>(p)); }
  template <class U>
  my_alloc(const my_alloc<U>& b) noexcept : no(b.no) { }
  explicit my_alloc(const int _no = 0) : no(_no) { }
  int no;
  using propagate_on_container_swap = std::true_type;
  //using propagate_on_container_copy_assignment = std::true_type;
  using propagate_on_container_move_assignment = std::true_type;
  my_alloc select_on_container_copy_construction() const { return my_alloc(no + 1); }
};

template <class T1, class T2>
bool operator==(const my_alloc<T1>& a1, const my_alloc<T2>& a2) noexcept
{
  return a1.no == a2.no;
}

template <class T1, class T2>
bool operator!=(const my_alloc<T1>& a1, const my_alloc<T2>& a2) noexcept
{
  return a1.no != a2.no;
}

template <class BidiIter>
using mymatch = std::match_results<BidiIter, my_alloc<std::sub_match<BidiIter>>>;

int main()
{
  mymatch<char*> mm1(my_alloc<std::sub_match<char*>>(1));

  // my_alloc は select_on_container_copy_construction を定義しているので、
  // コピーコンストラクタではそれを用いてアロケータを取得する。
  mymatch<char*> mm2(mm1);
  std::cout << mm1.get_allocator().no << ',' << mm2.get_allocator().no << std::endl;

  // my_alloc は propagate_on_container_swap を true_type としているので、
  // アロケータも swap される。
  swap(mm1, mm2);
  std::cout << mm1.get_allocator().no << ',' << mm2.get_allocator().no << std::endl;

  // my_alloc は propagate_on_container_copy_assignment を true_type としていないので、
  // アロケータは copy されない。
  mm1 = mm2;
  std::cout << mm1.get_allocator().no << ',' << mm2.get_allocator().no << std::endl;

  // my_alloc は propagate_on_container_move_assignment を true_type としているので、
  // アロケータも move される。
  mm1 = std::move(mm2);
  std::cout << mm1.get_allocator().no << std::endl;

  // move コンストラクタでは、アロケータも無条件に move される。
  mymatch<char*> mm3(std::move(mm1));
  std::cout << mm3.get_allocator().no << std::endl;
}

出力

1,2
2,1
2,1
1
1

バージョン

言語

  • C++11

処理系

備考

get_allocator の問題ではないが、GCC(libstdc++) の 4.9.2 までは代入演算子を使用した場合に正しくアロケータを設定しない。