Visual Studio 2017 C++ Tips2

Visual Studio 2017 の C++ 関連、その2

今度は 関連


前回とは違い、std::list 関連!
MFC で DLL を作っていて、設定項目を管理するのに std::list を使ってみたけど、他の vector や array でも良いんだと思います
年度別に管理してみようと思っていますので、list が良いかな?と単純に考えて見ましたが…さて⁉

 

std::list の宣言

#include <list>

struct DLLList {
    int    year;                //    年度
    std::wstring dll_path;      //    パス
    std::wstring dll_title;     //    表示名
    HMODULE hModue = NULL;
};

std::list<DLLList>    _dll_list;    //    リスト形式

こんな感じ
年度ごとに特定の処理をする DLL を用意して LoadLibrary してみようと目論んでみましたので、宣言はこんな感じ

 

リストの追加

この前の、swscanf のところの fgets でファイルを読んで処理します..

    _dll_list.clear();
    …
    while(0 != fgetws(wreadbuf, MAX_READ_BUF, fp)) {
        …
        DLLList tmp;
        tmp.year = year;
        tmp.dll_path = buf1;
        tmp.dll_title = buf2;
        _dll_list.push_back(tmp);
        …

    }

リストに項目を追加します
順番を指定したインサートとかもありますが、ソートとかする予定ですので読み込んだ順番にそのまま突っ込んでいきました
 

項目へのアクセス

突っ込んだ項目の、構造体のメンバーに変更を加えます
イテレーターを使わないで項目に直接アクセスしても、構造体のメンバーを変更できませんので、こんな感じで扱います

    for (auto iter = _dll_list.begin(); iter != _dll_list.end(); iter++) {
        …
        HMODULE hMod =  LoadLibraryW(iter->dll_path.c_str());
        iter->hModue = hMod;
        …

    }
begin から end まで、インクリメントしてイテレーターを進めて、要素にアクセスしてゆきます
 

ソート

比較関数は bool 型で引数は const で対象が二つ送られてきます
最初の引数が小さいときに真で、逆の時は偽を返すようです

bool    _dll_sort_comp(const DLLList& d1, const DLLList& d2) {
    bool ret = FALSE;
    if (d1.year < d2.year)
        ret = TRUE;
    return ret;
}

これで年度ごとの昇順にソートされます
実施はこんな感じ

    …
    _dll_list.sort(_dll_sort_comp);
    …

降順に並べるときは、真偽を逆に返します

比較関数では真偽しか返していませんので、比較する項目が同じ値の場合はプッシュした順になります
※ 比較が甘いときの事ですね..
ソート自体は void 型なので戻り値は無し

 

検索 find_if

指定された年度を持つ構造体をリスト中から返すには、こんな感じに無名関数を使います

    DLLList cmp{2005,L"",L"",NULL};
    auto iter = (_dll_list.begin(), _dll_list.end(),
            [cmp](DLLList t) {return t.year == cmp.year; });
    if( iter == _dll_list.end())
        MessageBoxW(0, L"not found", L"find", 0);
    else
        MessageBoxW(0, iter->dll_title.c_str(),L"find", 0);

year が 2005 の行をイテレーターへ返してきます
# 最近は、こんな書き方出来るんだ ^^.. JSer&PHPer なので割と得意だけど…何か馴染まないなぁ..
こう言う auto …. と言う書き方は ラムダ式と言うのか…
https://msdn.microsoft.com/ja-jp/library/dd293599.aspx
ここの、ラムダ式の説明にも find_if で開設しているなぁ…
PHP のクロージャーとか、JavaScript の無名関数とは少し趣が異なるのか?厳格化しているだけなのか?…
# PHP はそういう所がよく出来てるよなぁ…そのうち調べて見よう…

検索条件を別に指定できるなら、検索関数を指定する事が出来ます

bool _dll_find_func(const DLLList& t) {
    bool ret = FALSE;
  …
    if( 2005 == t.year) ret = TRUE;
  …
    return ret;
}
    …
    auto iter = std::find_if(_dll_list.begin(), _dll_list.end(), _dll_find_func);

こんな感じの比較関数を作ると、begin() から end() まで、全件聞いてきますので、条件に一致したら真を返します
# まぁ、検索をかけるならソートする必要も無いよね ^^;
 

検索 find

検索方法 その2

struct 宣言したときに、== オペレーターを書いておくと、std::find でも簡単に検索できる様です

    auto iter = std::find(_dll_list.begin(), _dll_list.end(), DLLList{2005,L"",L"",NULL});

上の find_if をこんな風に置き換え出来ます
struct では こんな風にオペレーターを指定しました

    bool operator == (const DLLList & tgt) {
        //    find 用のオペレータ
        if (this->year == tgt.year)
            return TRUE;
        return FALSE;
    }

で、オペレーターで比較できると言う事は…

struct DLLList {
    int    year;               //    年度
    std::wstring dll_path;     //    DLL のパス
    std::wstring dll_title;    //    DLL の表示名
    HMODULE hModue = NULL;

    bool operator == (const DLLList& tgt) {
        //    find 用のオペレータ
        if (this->year == tgt.year)
            return TRUE;
        return FALSE;
    }
    bool operator == (const int& year) {
        //    find 用のオペレータ 年度だけ比較
        if (this->year == year)
            return TRUE;
        return FALSE;
    }
};

こんな風に、 int 型の == オペレーターを指定すると、

    int tgt_year = 2005;
    auto iter = std::find(_dll_list.begin(), _dll_list.end(), tgt_year);

こんな感じの検索も出来ました ^^/
find_if にくらべて、こっちの方がシックリくる様な気がするけど…
# もしかして、const 型なので if 文の比較は year == this->year の方が良いのかな…
.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です