読者です 読者をやめる 読者になる 読者になる

貝柱が何かをする所

貝柱が何かをする所です、C++/Perl/その他諸々

メンバ変数のHidingの練習

C++
いいわけ

今週末は少々忙しかったので記事を書く余裕がなかった。
......というのは言い訳であまり今週は記事に出来るようなテクニックに触れてこなかった。
貝柱ではなく別のアカウントで、「同じ課題」に対して多数の言語でプログラムを書くという練習を行った。
そちらを記事にしても良いのだが、別件でもう少しプログラム内容について精査したいので、また改めて後日ということにする。
Scalaにもう少し深く触れたい。

まえがき

C++ではクラスを継承する際、継承元のメンバ変数を完全に上書きして"隠す"技が存在する。
俗に「Hiding」などと呼ばれるが、あまり良い実用例が思い浮かばない。

コード

何かに使えそうなテクニックだ。
どこかで使われているなら、ぜひ教えてほしい。

#include <iostream>
#include <functional>


//Base構造体
struct Base{
    std::function<void(int)> showInt;
};


//Baseから派生した構造体
struct SameBase : public Base{
    std::function<void(int, int)> showInt;
};


int main(void){
    SameBase base;
    base.showInt = [=](int value,int value2){
        std::cout << "show:" << value + value2 << std::endl;
    };
    base.showInt(20, 30);

    return 0;
}

上記のコードは継承元のshowIntをHidingしている。

overrideやoverloadとはまた違い、また別のテクニックとして何かできないだろうか?

Template Parameter PackをReverseする

まえがき

C++ではもはやおなじみになったTemplate Parameter Pack。今回はこれについてだ。

例えば、以下のように引数に与えられた値を出力するだけの関数があるとする。

template<typename Ty>
void shower(Ty head) {
	std::cout << head << std::endl;
}
template<typename Ty, typename... Ts>
void shower(Ty head, Ts... tail) {
	std::cout << head;
	shower(tail...);
}

これに対して、与えた逆順に出力してほしいものとする。
パラメータパックの逆展開だ。

コード

これには、stackoverflowの記事が大変参考になった。
c++ - How to reverse the order of arguments of a variadic template function? - Stack Overflow

これを基に以下のようにコードをおこした。

#include <iostream>

template<typename Ty>
void shower(Ty head) {
	std::cout << head << std::endl;
}
template<typename Ty, typename... Ts>
void shower(Ty head, Ts... tail) {
	std::cout << head;
	shower(tail...);
}

template<typename... Tn>
struct revert;

template<>
struct revert<>
{
	template<typename... Un>
	static void apply(Un const&... un) {
		shower(un...);
	}
};

template<typename Ty, typename... Ts>
struct revert<Ty, Ts...>
{
	template<typename ...Un>
	static void apply(Ty const& t, Ts const&... tail, Un const&... un) {
		revert<Ts...>::apply(tail..., t, un...);
	}
};

template<typename Ty, typename... Ts>
void reverse_shower(Ty const& val, Ts const&... tail) {
	revert<Ts...>::apply(tail..., val);
}

int main(void) {
	reverse_shower(1, 2, 3, 4, 5);

	/*
	reverse_shower<int, int ,int ,int ,int>( 1, 2, 3, 4, 5 )
	revert<int, int, int, int>::apply(2, 3, 4, 5, 1)
	revert<int, int, int>::apply(3, 4, 5, 2, 1)
	revert<int ,int>::apply(4, 5, 3, 2, 1)
	revert<int>::apply(5, 4, 3, 2, 1)
	revert<>::apply(5, 4, 3, 2, 1)
	shower(5, 4, 3, 2, 1)
	*/

	return 0;
}

非常に美しいテクニックだと思う。
実際に実用に取り入れられるかは分からないが、何かで実践的なコードを書いてみたい。

継承先のクラスポインタを格納した親ポインタに適切なクラスを構築する

まえがき

今、SuperというクラスからAとBが派生しているとする。
C++では、Superのポインタには、継承関係にあるAのインスタンス、Bのインスタンスがそれぞれ格納できる。
例えば以下の様な感じだ

Super* ptr = new A();
Super* ptr2= new B();

では、格納しているインスタンスによって、新たに親クラスポインタに派生したクラスポインタを格納したい場合はどうすればよいのだろう?

Super* ptr = new A();  //ただし、場合によってはnew B()となりうる
Super* ptr2 = ???;  //ptrの内容にあわせてAかBのインスタンスを格納したい

今回はこれを実現する

アプローチ

クラスが親子関係にあり、親クラスのメソッドを子クラスが継承したとする。
例えば、Superにshow()なるメソッドがあり、子クラスがそれを継承しているとすると、
次のコードでは

Super* ptr = new A();
ptr->show();

Superのshow()ではなく、Aのshow()が呼ばれる。これは多態性と呼ばれる特性によるものだ。

これを使い、自分自身のインスタンスを作成し返すファクトリ関数のようなものを持つことで、主題の問題を解決する

コード
#include <iostream>
#include <memory>

struct Super {
	virtual void show() {
		std::cout << "I am Super" << std::endl;
	}
	virtual std::unique_ptr<Super> make_me() = 0;
};

struct A : public Super {
	void show() override {
		std::cout << "I am A" << std::endl;
	}
	std::unique_ptr<Super> make_me() override {
		return std::unique_ptr<Super>(new A());
	}
};

struct B : public Super {
	void show() override {
		std::cout << "I am B" << std::endl;
	}
	std::unique_ptr<Super> make_me() override {
		return std::unique_ptr<Super>(new B());
	}
};

int main(void) {
	std::unique_ptr<Super> ptr_A = std::make_unique<A>();
	std::unique_ptr<Super> ptr_B = std::make_unique<B>();

	std::unique_ptr<Super> ptr_g = ptr_A->make_me();
	ptr_g->show();    // I am A
	ptr_g.reset();

	ptr_g = ptr_B->make_me();
	ptr_g->show();    // I am B

	return 0;
}

1つだけ値が有効な変数群を作成する

C++
まえがき

前回の記事からこの記事を書くまでにメインマシンに入れいているVisual Studioがバグってしまった。

具体的には起動時、VC++のテンプレートが見当たらなくなってしまった。それに基づき、C++のプロジェクトソリューションも正常に開くことが出来なくなってしまった。
Visual Studioフォーラムにも質問したが、望む回答が得られなかった。

この問題はVisual Studioを一旦完全にアンインストールし、再度Visual Studioをインストールすることで解決した。
下記記事が参考になった。
Visual Studio Uninstaller でvisual studio 2015 を完全アンインストール - Qiita

貝柱の環境では何回かexeを起動しなおさなければ完全にアンインストール出来なかった。

さて、前回に引き続き、今回の記事も万人向けとは言いがたい。
内容が中々にただC++で遊んでいるだけのものだが、暇な人はお付き合い願いたい。

動機

Windowsのコントロールの中にラジオボタンというものがある。
例えば、A B Cなどというラジオボタングループがあったら、そのウチ一つしか選べないようなコントロールだ。
これを管理しようと思うとどうなるだろうか?
例えば、以下のように単純に配列で管理する。

bool radio[3] = {true, false, false};

この場合、配列へのアクセスを管理する関数を別で用意して、配列の中のどれか一つだけをtrueにする。

しかし、C++を使っているならばクラスとして管理したい。
クラスとして管理すれば、アクセサを介するのでどれか一つがtrueになる事は保証できるだろう。
配列ならば管理も容易だ。

ラジオボタンの意味を持たせながら変数名を付けたいときはどうだろうか?

//ラジオボタン群...
bool chocolate = true;
bool coockie = false;
bool syrup = false;

変数名に意味合いがあると可読性がぐんとあがる。
だが代わりに管理が面倒だ。欲をいえば、例えば上記の例ならば、

coockie = true; //これをした時点で
assert( chocolate == false );
assert( syrup == false );
// これが満たされて欲しい

これを実現する。

アプローチ

以下にコードを示す。

#include <iostream>
#include <vector>
#include <functional>
#include <memory>

//型を梱包するもの
template<typename Ty>
class FlaggedType {
public:
	//ctor
	FlaggedType() {
		setter = &FlaggedType<Ty>::set;
	}
	virtual ~FlaggedType() = default;

	//=operator
	FlaggedType<Ty>& operator=(const FlaggedType<Ty>& other) {
		*this = other.val_;
		return *this;
	}
	FlaggedType(const FlaggedType<Ty>& other) {
		*this = other;
	}
	FlaggedType(const FlaggedType<Ty>&& other) {
		val_ = std::move(other.val_);
		ptr_ = std::move(other.ptr_);
		initializable_ = std::move(other.initializable_);
	}
	operator Ty() {
		return val_;
	}
	Ty& operator=(const Ty& val){
		//setterを経由した代入
		if (setter) {
			setter(*this, *this, val);
		}
		return val_;
	}

	//setter
	void set(FlaggedType<Ty>& base, const Ty& val) {
		base.val_ = val;
	}

	void only_set(FlaggedType<Ty>& base, const Ty& val) {
		//set処理によって値が変更される恐れがある
		//ダサいが一旦値をコピーしておく
		Ty value = val;
		//他の変数の値を初期化しつつセット
		for (auto& ele : base.ptr_) {
			ele->val_ = ele->initializable_;
		}
		base.val_ = value;
	}

	//setterを格納するstd::function
	std::function<void(FlaggedType<Ty>, FlaggedType<Ty>&, const Ty&)> setter;

//private:
	//実際に自分が格納している値
	Ty val_;

	//自身以外の他の変数ポインタを持つもの
	std::vector<std::shared_ptr<FlaggedType<Ty>>> ptr_;

	//自身が取るべき初期値
	Ty initializable_;
};

template<typename Ty>
void makeUniqueFlag(const Ty& initializable, std::vector<std::shared_ptr<FlaggedType<Ty>>>& vec, FlaggedType<Ty>& one) {
	//初期化値をセットし、リソースを破壊しないようにしながらポインタ作成
	one.setter = &FlaggedType<Ty>::only_set;
	std::shared_ptr<FlaggedType<Ty>> ptr(&one, [](FlaggedType<Ty>*) {});
	//格納
	vec.push_back(std::move(ptr));
	//格納
	for (auto& ele : vec) {
		ele->initializable_ = initializable;
		ele->ptr_ = vec;
	}
}
template<typename Ty,typename... Ts>
void makeUniqueFlag(const Ty& initializable, std::vector<std::shared_ptr<FlaggedType<Ty>>>& vec, FlaggedType<Ty>& head, Ts&... flags) {
	head.setter = &FlaggedType<Ty>::only_set;
	std::shared_ptr<FlaggedType<Ty>> ptr(&head, [](FlaggedType<Ty>*) {});
	//格納
	vec.push_back(std::move(ptr));

	makeUniqueFlag(initializable, vec, flags...);
}

template<typename Ty,typename... Ts>
void makeUniqueFlag(const Ty& initializable, Ts&... flags) {
	//ptrの初期化
	std::vector<std::shared_ptr<FlaggedType<Ty>>> ptr_vec;
	makeUniqueFlag(initializable, ptr_vec, flags...);
}

//Unionの解除
template<typename Ty>
void resetUniqueFlag(FlaggedType<Ty>& value) {
	value.setter = &FlaggedType<Ty>::set;
	value.ptr_.clear();
	value.ptr_.shrink_to_fit();
}

template<typename Ty, typename... Ts>
void resetUniqueFlag(FlaggedType<Ty>& head, Ts&... flags) {
	head.setter = &FlaggedType<Ty>::set;
	head.ptr_.clear();
	head.ptr_.shrink_to_fit();
	resetUniqueFlag(flags...);
}

int main(void){
	FlaggedType<bool> red;
	FlaggedType<bool> blue;
	FlaggedType<bool> yellow;
	
	red = true;
	blue = false;
	yellow = false;

	auto show_bool = [](const bool& boolean) {
		return (boolean ? "true" : "false");
	};

	std::cout << "red:" << show_bool(red) << std::endl;
	std::cout << "blue:" << show_bool(blue) << std::endl;
	std::cout << "yellow" << show_bool(yellow) << std::endl;

	std::cout << "make unique flag" << std::endl;

	makeUniqueFlag(false, red, blue, yellow);

	blue = true;

	std::cout << "red:" << show_bool(red) << std::endl;
	std::cout << "blue:" << show_bool(blue) << std::endl;
	std::cout << "yellow" << show_bool(yellow) << std::endl;

	return 0;
}

おそらくこのアプローチは完全ではない。

まず持つべきデータメンバをWrapしておきながらその実、publicになっており外部から容易にアクセスできる。
次におそらくsetterなどの渡し方はもう少し賢い方法があるはずだ。

実は記事の投稿が遅れたのは、このテーマを投稿しようとして解説文を考えていたが
色々と穴があり、結局良いアプローチが思い浮かばなかったというのもある(言い訳)。

たっぷりと時間が許された時に、もう少し綺麗に書いてみたいものだ。

非型テンプレートパラメータに指定できる値の制限をする

C++

自分の中でHotなうちに記事に書きおろそうと思う。
タイトルは非型テンプレートパラメータに制限を、と書いているが、doubleが使えないとかそういう事ではない。
もう少し単純な話だ。なお、この話はコアなのであまり万人には役に立たないかもしれない。
あと、以下の記事はVS2013で主に発案したので本来はconstexprを使用しなければならない所が多数ある事、
また、逆にいうとconstexprが使用できない制限下で行ったことを把握願いたい。

動機

C++ではご存知の通りテンプレートという強力な機構が存在する。
通常テンプレートパラメータには型を指定するが、次のように値を指定する事ができる。

template<int V>
struct Hoge{
    static const int value = V;
};
int main(void){
    std::cout << Hoge<10>::value << std::endl;
}

上記を非型テンプレートパラメータなどという。

ところで、ここで渡すパラメータに制限を持たせることはできないだろうか。
例えば正の整数のみで、負は許可しない。 以下のようなコードを書いた時、Hoge<-1>によってコンパイルエラーになってほしい。

Hoge<10>::value;        // ok. これは許可する
Hoge<-1>::value;        // no. これは許可しない

これを実現する。

アプローチ

まず必要になるのは、こちらが望む制限を実装するメタ関数だ。
これは単純に以下のように実装できる。

//内部に定数式が正負だったかの真偽値を持つメタ関数
template<int val>
struct is_positive{
    static const bool value = (val >= 0);
};
int main(void){
    if( is_positive<10>::value ){
        std::cout << "true" << std::endl;
    }
    
    return 0;
}

メタ関数is_positiveは内部valueに、非型テンプレートパラメータが制限を満たすかのbool値を持つ。

次に目的のクラスの実装を、以下のように行う

template<bool B, int V = 0>
struct positive_struct{
    positive_struct() = delete;
};

template<int V>
struct positive_struct<true, V>{
    positive_struct() = default;
    static const int val = V;
};

上記の実装はstd::enable_ifを参考にした。
こうすることによって、positive_structは第一テンプレートパラメータの真偽値によって、内部にvalを持つ場合、あるいはインスタンス化を抑制できる。
これを先ほどのメタ関数と合わせる。

#include <iostream>

//内部に定数式が正負だったかの真偽値を持つメタ関数
template<int val>
struct is_positive{
    static const bool value = (val >= 0);
};

template<bool B, int V = 0>
struct positive_struct{
    positive_struct() = delete;
};

template<int V>
struct positive_struct<true, V>{
    positive_struct() = default;
    static const int val = V;
};

template<int V>
using positive_struct_decl = positive_struct< is_positive<V>::value, V>;

int main(void){
    std::cout << positive_struct_decl<20>::val;
//    std::cout << positive_struct_decl<-15>::val;  これは存在しないのでコンパイルエラーになる
//  positive_struct_decl<-1> hoge;    これもエラー
   
    return 0;
}

実際には宣言を容易にするためにエイリアステンプレートを使う。
この実装を使えば、非型テンプレートの値によるインスタンス化の制限もできる。
また、嬉しい副作用としてVS2013以降ならば、コードを記述しただけでインテリセンスが働き、波線で注意してくれる。
(他のC++ IDEもいけるのかもしれない)

あとがき

なかなか需要がない実装かもしれない。
実際これを使おうと思った時にはどういう目的で使おうとしたのか忘れてしまった。
だが、せっかくなので記事にしてみた。 あと、やはり記事を書くのは時間がかかってしまう。

この記事を書きながら「この美術部には問題がある!」を見ていたのだが、自分も頭の中に思い描く嫁をあのようにキャンバスに上手く表したいものだ。

メモリリーク検出器とstd::unique_ptr

C++

久し振りに書く記事はC++は書けたがC++11をやりたての貝柱が実際にハマったことについて書こうと思う。
もちろん今でもその疎さはまだまだ解消されていないので初心者といえる。
はてなブログも久し振りに書くのでそのリハビリにも良いかもしれない。使い勝手が色々変わっていてまだ良くわかっていない。

貝柱は仕事柄C++IDEとしてVisual Studioを使っている。
もちろん都合上生ポインタも扱うのでメモリリークには気を使う。
Visual Studioには便利なメモリリーク検出器があり、Win32プロジェクトのDEBUGモードなら以下のコードによってメモリリークを検出できる。

#include <iostream>

//======== メモリリークの検出器 =======//
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

int main(void){

    //..... do something .....//

    _CrtDumpMemoryLeaks();
    return 0;
}

例えば、生ポインタを扱っていて、開放し忘れを検知したい時にこのコードは威力を発揮する。

_CrtDumpMemoryLeaks();

までにnewしたのにdeleteしなかったメモリが存在する場合、コンパイラは例えば以下のようにメモリダンプを吐き出す。

{63} normal block at 0x003F6A00, 80 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

ところで、C++11で追加されたstd::unique_ptrは、宣言したスコープから外れると、自動的に確保したメモリをdeleteしてくれる便利なスマートポインタだ。
例えば以下のような使い方をする。

{
    std::unique_ptr<int> p(new int(100));
} //ここでpは開放される

そこできちんとstd::unique_ptrによってメモリが開放されてるかを確認したいとする。
ハマったのは以下のように使用した時だった。

#include <iostream>
#include <memory>

//======== メモリリークの検出器 =======//
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif


int main(void){
    std::unique_ptr<int> p(new int(2));    

    _CrtDumpMemoryLeaks();
    return 0;
}

この例ではメモリリークを検知してしまう。何故だろう。答えは本当に至極単純だ。
_CrtDumpMemoryLeaks()はその時点で開放されていないメモリをダンプする。
一方std::unique_ptrの開放タイミングはそのスコープが外れる時だ。すなわち、_CrtDumpMemoryLeaks()の後になる。
_CrtDumpMemoryLeaks()はスコープから外れていないstd::unique_ptrのメモリをメモリリークとみなし、ダンプしてしまうわけだ。
なので、以下のようにコードをスコープで囲まなければならない。

#include <iostream>
#include <memory>

//======== メモリリークの検出器 =======//
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

int main(void) {
    {
        std::unique_ptr<int> p(new int(2));
    }

    _CrtDumpMemoryLeaks();
    return 0;
}

初歩的なミスで熟練には笑われてしまうかもしれない。
特にカスタムデリータのテストをしたい時などに短いプログラムを書くときは、注意しておこう。

最初の記事

とりあえず貝柱としての技術ブログを始めなければならないという衝動にかられた。

ので色々を書いていくことにする。

貝柱のお部屋のFFFTPパスワードを忘れてしまった。更新したいところだがどうしたものか。