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

履歴 編集

function template
<scoped_allocator>

std::scoped_allocator_adaptor::construct(C++11)

template <class T, class... Args>
void construct(T* p, Args&&... args);                         // (1)

template <class T1, class T2, class... Args1, class... Args2>
void construct(pair<T1, T2>* p, piecewise_construct_t,
               tuple<Args1...> x, tuple<Args2...> y);         // (2) C++17 まで

template <class T1, class T2>
void construct(pair<T1, T2>* p);                              // (3) C++17 まで

template <class T1, class T2, class U, class V>
void construct(pair<T1, T2>* p, U&& x, V&& y);                // (4) C++17 まで

template <class T1, class T2, class U, class V>
void construct(pair<T1, T2>* p, const pair<U, V>& x);         // (5) C++17 まで

template <class T1, class T2, class U, class V>
void construct(pair<T1, T2>* p, pair<U, V>&& x);              // (6) C++17 まで

概要

p で指定された領域に、inner_allocator() と指定された引数で uses-allocator 構築を行う。
また、*ppair だった場合は、それぞれの要素に対して inner_allocator() と指定された引数で uses-allocator 構築を行う。

効果

説明を簡略化するために、以下の説明用関数を使用する。

備考

  • C++20 における変更は、一見新規導入されたユーティリティ関数(uses_allocator_construction_args)を使用して定義を簡略化しただけのように思えるが、実はこの変更によりネストした pair に対しても uses-allocator 構築がサポートされるように改善されている。

#include <cassert>
#include <vector>
#include <string>
#include <scoped_allocator>

template <class T>
using alloc_t = std::allocator<T>;

// コンテナの要素(Inner)
using string = std::basic_string<
  char,
  std::char_traits<char>,
  alloc_t<char>
>;

// コンテナ(Outer)
template <class T>
using vector = std::vector<
  T,
  std::scoped_allocator_adaptor<alloc_t<T>, alloc_t<typename T::value_type>>
>;

template <class T>
using pair_of_vector = std::vector<
  T,
  std::scoped_allocator_adaptor<alloc_t<T>>
>;

// (1)
void construct_propagate_alloc()
{
  vector<string>::allocator_type alloc {
    alloc_t<string>(), // vector自体のアロケータオブジェクト
    alloc_t<char>()    // vectorの全ての要素に使用するアロケータオブジェクト
  };

  // 外側のアロケータを使用し、stringが1要素入るメモリを確保
  const std::size_t n = 1;
  string* p = alloc.allocate(n);

  // (1) 以下のコンストラクタを呼び出し、アロケータオブジェクトを伝播させる
  // basic_string(const char*, Allocator)
  alloc.construct(p, "hello");

  // オブジェクトを破棄
  alloc.destroy(p);

  // メモリを解放
  alloc.deallocate(p, n);
}

void construct_pair()
{
  pair_of_vector<std::pair<string, string>>::allocator_type alloc;

  const std::size_t n = 5;
  std::pair<string, string>* p = alloc.allocate(n);

  // (2)
  // pairの各要素に対して以下のコンストラクタを呼び出し、
  // アロケータオブジェクトを伝播させる。
  // basic_string(const char*, Allocator)
  std::pair<string, string>* pair_p = p;
  alloc.construct(p, std::piecewise_construct,
                  std::forward_as_tuple("hello"),
                  std::forward_as_tuple("world"));
  assert(pair_p->first == "hello");
  assert(pair_p->second == "world");

  // (3)
  // pairの要素をデフォルト構築する。
  pair_p = std::next(pair_p);
  alloc.construct(pair_p);
  assert(pair_p->first == "");
  assert(pair_p->second == "");

  // (4)
  // pairの各要素のコンストラクタ引数をひとつずつ受け取って構築
  pair_p = std::next(pair_p);
  alloc.construct(pair_p, "hello", "world");
  assert(pair_p->first == "hello");
  assert(pair_p->second == "world");

  // (5)
  // pairの各要素のコンストラクタ引数をひとつずつ、
  // まとめてpairとして受け取り、それぞれをtupleに分解して構築
  pair_p = std::next(pair_p);
  std::pair<const char*, const char*> fifth_args("hello", "world");
  alloc.construct(pair_p, fifth_args);

  // (6)
  // pairの各要素のコンストラクタ引数をひとつずつ、
  // まとめてpairとして受け取り、それぞれをtupleに分解して転送して構築
  pair_p = std::next(pair_p);
  alloc.construct(pair_p, std::make_pair("hello", "world"));

  for (std::size_t i = 0; i < n; ++i) {
    alloc.destroy(p + i);
  }

  alloc.deallocate(p, n);
}

int main()
{
  construct_propagate_alloc();
  construct_pair();
}

出力

バージョン

言語

  • C++11

処理系

関連項目

参照