はかせのラボ

私の頭の中を書いていく雑記ブログです

C++ タスクシステム⑬ ~はかせはカスタムデリータを覚えた~

あいさつ

どうも、はかせです。
昨日カスタムデリータが使えないorz
という旨の記事を出しました。

その問題がようやく解決できたので記事にします。

なぜできなかったのか

unique_ptrのカスタムデリータを指定した場合
unique_ptrのコンストラクタで使用するテンプレートのコンストラク
解放時に呼ぶ処理をそれぞれ渡す必要があったみたいです。
言葉で説明するよりも実際のコードを見た方がわかると思います。

std::unique_ptr<ReactiveProperty<double>, Deleter<ReactiveProperty<double>>> doubleRP;

//コンストラクタにテンプレートのコンストラクタとカスタムデリータの解放処理をそれぞれ渡す必要があった模様
doubleRP = 
	std::unique_ptr<ReactiveProperty<double>, Deleter<ReactiveProperty<double>>>
	(new ReactiveProperty<double>(), Deleter<ReactiveProperty<double>>());

昨日までの私のコードではunique_ptrのコンストラクタに
必要な引数を渡していなかったため
失敗してnullptrが入ってしまっていたということになります。

あまりこのことについて言及している記事が見つけれられなかったため
気づくのに大分時間がかかってしまいました‥
(私が無知なだけで当たり前のことなんでしょうね)

コードが長い・・・

もう一度コードを見てください。

std::unique_ptr<ReactiveProperty<double>, Deleter<ReactiveProperty<double>>> doubleRP;

//コンストラクタにテンプレートのコンストラクタとカスタムデリータの解放処理をそれぞれ渡す必要があった模様
doubleRP = 
	std::unique_ptr<ReactiveProperty<double>, Deleter<ReactiveProperty<double>>>
	(new ReactiveProperty<double>(), Deleter<ReactiveProperty<double>>());

改めて見てみると一行がとても長いです。
改行を入れても長いと感じるので相当だと思います。

よく見てみるとReactiveProperty<double>というワードが頻出しています。
これを短い別名に出来たら結構短くなりそうです。

それを実現する方法がC++にはあります。
エイリアステンプレートです。

エイリアステンプレート

型に別名をつける機能です。
using句を使って宣言します。

using Property = ReactiveProperty<double>;

これでReactiveProperty<double>はPropertyという別名で宣言して
使うことが出来るようになりました。

//エイリアステンプレートを使って名前を短縮
using Property = ReactiveProperty<double>;

//コンストラクタにテンプレートのコンストラクタとカスタムデリータの解放処理をそれぞれ渡す必要があった模様
//エイリアステンプレート無し
std::unique_ptr<ReactiveProperty<double>, Deleter<ReactiveProperty<double>>> doubleRP;

doubleRP = 
	std::unique_ptr<ReactiveProperty<double>, Deleter<ReactiveProperty<double>>>
	(new ReactiveProperty<double>(), Deleter<ReactiveProperty<double>>());

//エイリアステンプレート有り
std::unique_ptr<Property, Deleter<Property>> doubleRP2;

doubleRP2 = 
	std::unique_ptr<Property, Deleter<Property>>
	(new Property(),Deleter<Property>());

比較してわかりやすいよう同じように改行を入れています。
コードが短くなり読みやすくなったと思います。

実行

コード

int main(int argc, char const* argv[])
{
#if _DEBUG
	_CrtSetDbgFlag
	(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
#endif

	//エイリアステンプレートを使って名前を短縮
	using Property = ReactiveProperty<double>;

	//コンストラクタにテンプレートのコンストラクタとカスタムデリータの解放処理をそれぞれ渡す必要があった模様
	//エイリアステンプレート無し
	std::unique_ptr<ReactiveProperty<double>, Deleter<ReactiveProperty<double>>> doubleRP;

	doubleRP = 
		std::unique_ptr<ReactiveProperty<double>, Deleter<ReactiveProperty<double>>>
		(new ReactiveProperty<double>(), Deleter<ReactiveProperty<double>>());

	doubleRP->Subscribe([&](double value)->void {std::cout << "doubleRP:" << value << std::endl; });
	*doubleRP = 1000;

	//エイリアステンプレート有り
	std::unique_ptr<Property, Deleter<Property>> doubleRP2;

	doubleRP2 = 
		std::unique_ptr<Property, Deleter<Property>>
		(new Property(),Deleter<Property>());

	doubleRP2->Subscribe([&](double value)->void {std::cout << "doubleRP2:" << value << std::endl; });
	*doubleRP2 = 1000;

	getchar();
	//解放
	doubleRP.reset();
	doubleRP2.reset();
	getchar();
}

実行結果
f:id:hakase0274:20181231182506p:plain

あとがき

今回は前回詰まっていたカスタムデリータが使えるようになったという記事でした。
おそらくちゃんとリファレンスとか紹介記事を読んでいれば
詰まることなく進んだのかなと思います。

ただ私がこうやって詰まることで私だけでなく、
同じように詰まる方の手助けになると思って笑っておきます。

それでは今回はこの辺でノシ