きままにブログ

プログラミングを主とした私のメモ帳です。寂しいのでコメントください笑

リファレンスクラス

定数を返すには巨大過ぎるデータを扱う場合できれば参照やポインタで返したいです。ところが、ポインタを直接渡すと、そのポインタが変更されるような場合困ります。

そもそも参照やポインタで返すべきではないのですが、場合によっては参照で受け取りたいような時があります。まず、=演算子や*演算子は通常参照を返します。ただし返すのは*thisですね。こうすることで戻り値もその対象とナブオブジェクト自信と同等に扱えるようになって便利なのです。

ポインタで返すことは通常有り得ません。返すならスマートポインタを利用します。ところが、ポインタの中身が変更されうるようなケースでは「参照」を返せません。即ちスマポでも困るような場合です。

そういうときは直接index等を返しますが、汎用性に掛けます。そこでRferenceクラスを作ってそのReferenceを返すことで後でこれを用いてアクセスできるというわけです。

#include <cstdio>
#include <vector>

template <typename Friend, typename IDType>
class Reference {
	friend typename Friend;
public:
	Reference(const Reference& it) : id(it.id) { }
	Reference& operator=(const Reference& it) { id = it.id; }
private:
	Reference(IDType id) : id(id) {}
	operator IDType() { return id; }
	IDType id;
};

class C {
	using ref = Reference < C, int > ;
public:
	ref create(int x) {
		v.push_back(x);
		size_t index = v.size() - 1;
		return ref(index);
	}
	int get(ref id) {
		return v[id];
	}
private:
	std::vector<int> v;
};

int main() {
	C c;
	auto it = c.create(10);
	auto it2 = c.create(20);
	printf("%d, %d", c.get(it), c.get(it2)); // 10, 20
}