boostのrefが必要になったので作ってみた


boostにあるref相当の物が必要になりました。
なので作ってしまいます。


template
class reference_holder {
T& val_;
public:
reference_holder(T& arg) : val_(arg) {} // Tのリファレンスを保持
operator T&() { return val_; } // 型変換を利用してTのリファレンスを返す
};

リファレンスを保持するテンプレートクラスreference_holderを作り
型変換演算子operator T&でリファレンスを返すようにします。

ここまででお試し


void mod_string(std::string& str)
{
str = "abcdef";
}

int main()
{
std::string str("test");
std::cout << str << std::endl; // test
mod_string(reference_holder(str));
std::cout << str << std::endl; // abcdef
}

きちんとabcdefが表示されます。
しかし、このままだとreference_holderに毎回型情報を与えなければ使えないので不便です。
boostのようにref(str)と書きたい。
じゃどうするか?reference_holderに型情報を転送するためのラッパテンプレート関数を用意します。


template reference_holder ref(T& arg) {
return reference_holder(arg); // reference_holderに型情報を転送
};

お試し


void mod_string(std::string& str)
{
str = "abcdef";
}

int main()
{
std::string str("test");
std::cout << str << std::endl; // test
mod_string(ref(str)); // テンプレート関数refからreference_holderに型情報を転送
std::cout << str << std::endl; // abcdef
}

これで目的は達成です。しかし問題がまだ一つあります。
refに渡す引数のconstを保障させたい場合があります。
そのためconstを保障させるバージョンのラッパー関数を用意します。


template reference_holder cref(const T& arg) {
return reference_holder(arg); // reference_holderにconstな型情報を転送
};

お試し


void disp_stringaddr(const std::string& str) {
std::cout << &str << std::endl;
}

int main() {
std::string str("test");
std::cout << &str << std::endl;
disp_stringaddr(cref(str)); // constを保障
std::cout << &str << std::endl;
return 0;
}

これでconstを保障できるようになりました。
ためしに
void disp_stringaddr(const std::string& str)この行を
void disp_stringaddr(std::string& str)
こう変更してコンパイルをしてみてください。
reference_holderからstd::string &に変換できない種のエラーが出てくれます。