C言語で多値返却

ちょっと古いけどhttp://d.hatena.ne.jp/yuyarin/20090825/1251136545の話。

C標準では。

C言語の仕様レベルでは多値返却にもっとも近いのは構造体の値返却だ。複数の値を返すという用途は充分に満たしている。

struct int_int_t {
  int x;
  int y;
};
struct int_int_t func(void);

しかし、構造体の値返却は同じ構造体を用いて受け取らなくてはならない。例えば

int main() {
  int x;
  int y;
  <x, y> = func();
  ...do somthing...
  <y, x> = func();
  return 0;
}

という処理はC言語には存在しない。

ゼロ・オーバーヘッド。

受け取る側が構造体ならアドレスを受け取ってmemcpy()するだけで済むが、受け取る側が変数二つからなる多値の場合には返り値を二つの変数に分けてコピーする必要がある。C言語の基本機能にはそのようなものがない以上、今から標準に入ることは期待し辛いのではないかと思う。
しかし、C++では非PODクラスの代入ではメンバごとの代入が行われる。つまり、非PODクラスとして多値を実装するのはゼロ・オーバーヘッドとして許されるのかもしれない。

というわけで実装してみた。

#include <stdio.h>

template <typename X, typename Y>
struct Values {
  struct Ret {
    X const x;
    Y const y;
    Ret(X const &_x, Y const &_y)
      :x(_x), y(_y) {
    }
  };
  struct Ref {
    X &x;
    Y &y;
    Ref(X &_x, Y &_y)
      :x(_x), y(_y) {
    }
    Ref& operator=(Ret const& ret) {
      x = ret.x;
      y = ret.y;
    }
  };
};

Values<int, int>::Ret func() {
  return Values<int, int>::Ret(1, 2);
}

int main() {
  int x;
  int y;
  Values<int, int>::Ref(x, y) = func();

  printf("%d, %d\n", x, y);
  
  return 0;
}