C++0x の std::pair

C++0x では std::pair が狂信的な速度狂や偏屈な例外安全性狂信者のため、もとい、より安全で高速なソフトウェアのために、便利になりました。

#include <cstdio>
#include <utility>
struct S {
  /* implicit */ S(int){ printf("implicit ctor\n"); }
  S(const S&){ printf("copy ctor\n"); }
};

int main(){
  std::pair<S, int> p(1, 1);
  return 0;
}

上のコードを実行すると、0x 以前の C++ では int から S 構造体への暗黙の変換のために implicit な unary constructor が呼び出され、その後コピーコンストラクタが呼び出されます。
C++0x の std::pair では、これは implicit な unary constructor の呼び出し一回で済みます。
これは、格納する値の型へ変換可能な型の値を引数としてとるコンストラクタが追加されたためです。

とはいえコンストラクタの呼び出し回数を減らすために implicit なコンストラクタを宣言するというのは馬鹿げていますし、複数の引数を取ることができません。
そんなわけで「値そのものではなく、値を生成するのに必要なコンストラクタの引数を渡して、内部でコンストラクタの呼び出しを行う」コンストラクタの登場です。

// C++0x only
#include <cstdio>
#include <utility>
#include <tuple>
struct S {
  S(const S&){ printf("copy ctor\n"); }
  S(int, int){ printf("ctor\n"); }
};

int main(){
  std::pair<S, int> p(std::piecewise_construct_t(), std::pack_arguments(1, 1), std::pack_arguments(1));
  return 0;
}

上のコードではコピーコンストラクタは呼び出されません。
通常のコンストラクタと区別するために、頭にタグとなる型「piecewise_construct_t」の値を渡してやります。残る二引数が、first と second のコンストラクタへ渡す引数のパックです。std::pack_arguments は rvalue を保持する tuple を返すヘルパー関数です。あまり気にしないでください。

まあ std::pair とか使うのは unordered_map 使う時ぐらいかも知れませんが…