情報系の手考ノート

数学とか情報系の技術とか調べたり勉強したりしてメモしていきます.

任意の型の値と参照値の両方を保持できるクラス(C++17)

あるプログラムが下のようになっていたとする。

int a = 10;
value A = a;
value B = 20;

cout << A << endl;
cout << B << endl;
a = 30;
cout << A << endl;

このとき実行結果が

10
20
30

のようになるようなクラスを作れないかと考えたことがあった。

考えた当時は実装方法が検討もつかなかったが最近になって実装出来たので、自分へのメモとして書いておく。

(この程度のことを書くのもどうかとも思ったが、どうせ自分で実装を忘れそうだったのでメモとして書くことにした。)

実装

以下に実装を示す。

template <class T>
class value {
    T val;
public:
    constexpr value(T&& v) : val(v) { }
    constexpr auto operator () () -> std::conditional_t<std::is_lvalue_reference<T>::value, T, T&> { return val; }
};
template <class T>
value(T&& a) -> value<T>;

ユニバーサル参照とc++17で実装されたクラステンプレートのテンプレート引数推論を用いて、コンストラクタに渡された変数が右辺値なら値を受け取り、左辺値なら参照値を保持する。

このvalueクラスを使えばこの記事の冒頭でのプログラムを

int a = 10;
value A(a);
value B(20);

cout << A << endl;
cout << B << endl;
a = 30;
cout << A << endl;

と書き変えることで、冒頭での実行結果と同じ結果が得られる。

おわりに

実装してみて、正直たいして難しいことでもなかったなぁという感想だった。 今回は実装しなかったが、代入演算子などを実装すれば別のvalueからの受け取りなども可能だと考えられるので、時間があれば実装してみたい。