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

ゆとりーなの日記

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

traitsな加算を実装しようと思ったときの話

とある構造体、

struct hoge {
  int x, y;
};

があったときに、普通にaddを実装すると、

void add(hoge &lhs, const hoge &rhs) {
  lhs.x += rhs.x;
  lhs.y += rhs.y;
}

って感じになるかと思います。で、今流行りのtraitsチックに書くと、

template <typename T>
struct traits {
  static void set_x(T &t, int x) {
    t.x = x;
  }

  static void set_y(T &t, int y) {
    t.y = y;
  }

  static int get_x(const T &t) {
    return t.x;
  }

  static int get_y(const T &t) {
    return t.y;
  }
};

void add(hoge &lhs, const hoge &rhs) {
  traits<hoge>::set_x(lhs, traits<hoge>::get_x(lhs) + traits<hoge>::get_x(rhs));
  traits<hoge>::set_y(lhs, traits<hoge>::get_y(lhs) + traits<hoge>::get_y(rhs));
}

みたいな感じになってしまうかと思います。元のやつはoperator +=だけで完結しているのに対し、traitsチックなやつはoperator +したものを代入に加え函数呼び出しが沢山含まれています。lhs.x = lhs.x + rhs.x;位であれば最適化で元の子と同じコードを吐いてくれそうですが、ここまで複雑になった場合にコンパイラは空気を読んでくれるのでしょうか。
 結論から言うと読んでくれました。どちらもVC++2010EEのReleaseビルドに於いて、該当アセンブリは以下のようになっていました。

mov	edx, DWORD PTR [ecx]
mov	ecx, DWORD PTR [ecx+4]
add	DWORD PTR [eax], edx
add	DWORD PTR [eax+4], ecx

 念のため浮動小数点の場合も。

fld	DWORD PTR [eax]
fadd	DWORD PTR [ecx]
fstp	DWORD PTR [eax]
fld	DWORD PTR [ecx+4]
fadd	DWORD PTR [eax+4]
fstp	DWORD PTR [eax+4]

 traitsチックに書いた場合に遅くなるのではという心配は特になさそうです。