読者です 読者をやめる 読者になる 読者になる

ゆとりーなの日記

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

VC++2010のfor_eachはクソい?

取り敢えず次のコードを見てください。

#include <iostream>
#include <vector>
#include <algorithm>

struct func {
  func() {
    std::cout << "ctr" << std::endl;
  }

  func(const func &) {
    std::cout << "copy ctr" << std::endl;
  }

  func(func &&) {
    std::cout << "move ctr" << std::endl;
  }

  void operator ()(const int x) const {
  }
};

int main() {
  std::vector<int> v(10);
  std::for_each(v.begin(), v.end(), func());
  return 0;
}

実行結果

ctr
copy ctr
move ctr

ファンクタにrvalue渡してるのにコピーコンストラクタが起動してます。
因みにVC++2010のfor_eachは内部でイテレータとファンクタのチェックを行ったあと(デバッグビルド時のみ?)、_For_eachに投げるということをやっているみたいなので、実質for_eachの実装は_For_eachです。多分。
というわけでこいつを直接呼んでやると、

#include <iostream>
#include <vector>
#include <algorithm>

struct func {
  func() {
    std::cout << "ctr" << std::endl;
  }

  func(const func &) {
    std::cout << "copy ctr" << std::endl;
  }

  func(func &&) {
    std::cout << "move ctr" << std::endl;
  }

  void operator ()(const int x) const {
  }
};

int main() {
  std::vector<int> v(10);
  std::_For_each(v.begin(), v.end(), func());
  return 0;
}

実行結果

ctr
move ctr

さすがVC++2010。私たちに出来ない事を平然とやってのけます。
多分一番問題になるのは、こいつがコンパイル通らない事ですかね。

#include <iostream>
#include <vector>
#include <algorithm>

struct func {
  func() {
    std::cout << "ctr" << std::endl;
  }

  func(func &&) {
    std::cout << "move ctr" << std::endl;
  }

  void operator ()(const int x) const {
  }

 private:
  func(const func &) {
    std::cout << "copy ctr" << std::endl;
  }
};

int main() {
  std::vector<int> v(10);
  // コピコンが働くせいでコンパイルでこける
  std::for_each(v.begin(), v.end(), func());
  return 0;
}

規格にはコピコン消されてても大丈夫だよ的なことが書いてあるっぽいのですがこれでは・・・。