最終更新日時:
が更新

履歴 編集

function
<ios>

std::ios_base::pword

void*& pword(int idx);

概要

void* 型の私用記憶域への参照を取得する。

効果

idx で指定した記憶域がまだ確保されていなかった場合、新たに void* 型の記憶域を確保し、ヌルポインタで初期化する。 もし、記憶域の確保に失敗し、かつ、*thisbasic_ios の基底サブオブジェクトの場合、basic_ios::setstate(badbit) を呼び出す(これは failure 例外を送出するかもしれない)。

戻り値

idx で指定した記憶域への参照。もし記憶域が確保できなかった場合(かつfailure 例外が投げられなかった場合)には、ヌルポインタに初期化された有効な void* 型への参照。

備考

  • 引数 idx には、xalloc で取得した値を渡すことが想定されている。 そうすることによって、各プログラムが他のプログラムと競合すること無く各ストリームオブジェクト内に void* 型の私用記憶域を確保することが可能となる。
  • 本関数で取得した void* への参照は、本オブジェクトの他の操作によって無効になる可能性がある。
    しかし、その場合でも引数 idx で指定した記憶域の内容は依然として有効である。
  • 本関数で取得した void* 型の記憶域の内容は、basic_ios::copyfmt でコピーされる。
    ただし、コピーされるのはあくまでもポインタ値であるため、必要に応じてコールバックで対処を行うこと。(下記の例も参照)

#include <iostream>
#include <string>
#include <sstream>

// 任意の接尾辞を付加出力可能な string 型
struct MyString {
  std::string value;
};

// 接尾辞を指定するためのマニピュレータ
struct setsuffix {
  explicit setsuffix(const std::string& suffix) : suffix(suffix) {}
  friend std::ostream& operator<<(std::ostream& os, const MyString& x);
  friend std::ostream& operator<<(std::ostream& os, const setsuffix& manip);
private:
  std::string suffix;
  static const int index;
  static void callback(std::ios_base::event ev, std::ios_base& str, int index) {
    void*& psuffix = str.pword(index);
    switch (ev) {
    case std::ios_base::erase_event:
      // デストラクタ、および、copyfmt のコピー前に string を delete
      delete static_cast<std::string*>(psuffix);
      break;
    case std::ios_base::copyfmt_event:
      // copyfmt のコピー後に string を複製
      psuffix = new std::string(*static_cast<std::string*>(psuffix));
      break;
    case std::ios_base::imbue_event:
      break;
    }
  }
};

// 記憶域用の添え字を取得
const int setsuffix::index = std::ios_base::xalloc();

// MyString 用の出力演算子
std::ostream& operator<<(std::ostream& os, const MyString& x)
{
  std::string* psuffix = static_cast<std::string*>(os.pword(setsuffix::index));
  return os << (psuffix == 0 ? x.value : x.value + *psuffix);
}

// マニピュレータ用の出力演算子
std::ostream& operator<<(std::ostream& os, const setsuffix& manip)
{
  void*& psuffix = os.pword(setsuffix::index);
  if (!os.bad()) {
    if (psuffix == 0) {
      // 初回はコールバックを登録して、string を割り当てる
      os.register_callback(setsuffix::callback, setsuffix::index);
      psuffix = new std::string(manip.suffix);
    } else {
      *static_cast<std::string*>(psuffix) = manip.suffix;
    }
  }
  return os;
}

int main()
{
  MyString x = {"今日も一日がんばる"};

  std::cout << x << std::endl;                          // 普通に出力
  std::cout << setsuffix("ドン") << x << std::endl;     // どんちゃん風に出力

  std::stringstream ss;
  ss << setsuffix("ぞい");                              // ss を涼風青葉風出力に設定
  std::cout.copyfmt(ss);                                // ss から std::cout にフォーマットをコピー
  ss << setsuffix("(´・_・`)");                           // ss を tanakh さん風に設定変更
  std::cout << x << std::endl;                          // 涼風青葉風に出力(ss に対する変更は無影響)
}

出力

今日も一日がんばる
今日も一日がんばるドン
今日も一日がんばるぞい

なお、上記の例はコールバックで例外の適切な処置を行っていないので注意。
(コールバックは例外を送出してはいけない。register_callback の要件を参照)

参照