ゆとりーなの日記

日記的な事を書いて行くと思はれる

make_tupleはmoveされない

とあるサウンド系のコードを書いていた時の事。サウンドの波形データと波形フォーマットを一度に返したいなぁということでtupleを返す事にしたわけです。

std::tuple<std::vector<std::uint8_t>, format_t> load_wave_file(const std::string &file_name) {
  std::ifstresm fin(file_name, std::ios::in | std::ios::binary);
  format_t format:
  // フォーマット読み込み
  std::vector<std::uint8_t> buffer(size);
  fin.read(reinterpret_cast<char *>(&buffer.front(), buffer.size()));
  return std::make_tuple(std::move(buffer), format);
}

普通wavファイルの波形データは馬鹿でかいですからコピーされては困ります。今回は戻り値が関数経由なのでstd::moveで明示的にbufferをmoveしてやるのが良さそうです。
ところがこの関数を実行してみるとアホみたいに時間がかかるんですね。残念ながら波形データのコピーが行われてしまってるみたいなんです。
make_tupleを諦めて型を明示的に生成して返してやるとほぼ遅延なしで制御が返ってくる事からちゃんとmoveされるみたいです。

std::tuple<std::vector<std::uint8_t, format_t> load_wave_file(const std::string &file_name) {
  std::ifstresm fin(file_name, std::ios::in | std::ios::binary);
  format_t format:
  // フォーマット読み込み
  std::vector<std::uint8_t> buffer(size);
  fin.read(reinterpret_cast<char *>(&buffer.front(), buffer.size));
  return std::tuple<std::vector<std::uint8_t>, format_t>(std::move(buffer), format);
}

型推論か何かの関係なんでしょうか。
追記:
すばる先生をはじめとする識者によってmsvc10に付属のmake_tupleの実装が以下略という結論に至りました。