嘘です。必要はないです。
ただ「モジュール化したいな。dllっての使ってみるか。」と思いついただけです。
調べてみたらlibファイル作るのとそう変わらないようだったので楽勝^^
と、思っていた時期が僕にもありました^p^
dllでクラスをexportする際、メンバにvectorを持っていると警告が出ます。
(vectorだけではなくmapとかlistでも出るっぽいです)
なんか無視しても問題ない警告らしいのですがうざったいので解消したいです。
色々調べた結果、exportするクラスはインターフェイスクラスが良さげな感じです。
つまりdllでクラスをexportしたい場合は
- インターフェイスクラス(exportする)
- インターフェイスクラスを継承したインナークラス(exportしない)
- インターフェイスクラスを返す関数(exportする)
今回はデータを収集するクラスをdll化しました。
以下コード
エイリアス宣言
► スポイラーを表示
► スポイラーを表示
SamplesInterface.h
visualstudioだと __interface というキーワードが用意されていて、
これを使うと virtual とか =0 とかが省略できる。
らくちん
#pragma once
#ifdef SAMPLES_DLL
#define SAMPLES_API __declspec(dllexport)
#else
#define SAMPLES_API __declspec(dllimport)
#endif
#include
namespace RL
{
__interface SAMPLES_API Samples
{
void SetSharpSize(const int &sharp_size);
void Sharp(const int &max_memory);
void Add
(
const State ¤t,
const Action &action,
const Reward &reward,
const State &transition,
const Terminate &terminate
);
void Shuffle();
void Marge(const Samples &samples);
void Clear();
void GetBatch(const Samples &samples,const int &batch_size);
const RL::StateArray& ReadCurrent()const;
const RL::ActionArray& ReadAction()const;
const RL::RewardArray& ReadReward()const;
const RL::StateArray& ReadTransition()const;
const RL::TerminateArray& ReadTerminate()const;
const int& ReadArraySize()const;
bool Destroy();
};
}
これを使うと virtual とか =0 とかが省略できる。
らくちん
► スポイラーを表示
InnerSamples.h
#pragma once
#include
#include"SamplesInterface.h"
namespace RL
{
class InnerSamples
:public Samples
{
private:
StateArray current_array;
ActionArray action_array;
RewardArray reward_array;
StateArray transition_array;
TerminateArray terminate_array;
int array_size;
int sharp_size;
public:
InnerSamples();
void SetSharpSize(const int &sharp_size)override;
void Sharp(const int &max_memory);
void Add
(
const State ¤t,
const Action &action,
const Reward &reward,
const State &transition,
const Terminate &terminate
);
void Shuffle();
void Marge(const Samples &samples);
void Clear();
void GetBatch(const Samples &samples,const int &batch_size);
const RL::StateArray& ReadCurrent()const;
const RL::ActionArray& ReadAction()const;
const RL::RewardArray& ReadReward()const;
const RL::StateArray& ReadTransition()const;
const RL::TerminateArray& ReadTerminate()const;
const int& ReadArraySize()const;
bool Destroy();
};
}
► スポイラーを表示
MainMethod.cpp
[Add, MakeBatch, Mearge, Clear]
[Add, MakeBatch, Mearge, Clear]
#include "InnerSamples.h"
void RL::InnerSamples::Add
(
const State & current,
const Action & action,
const Reward & reward,
const State & transition,
const Terminate & terminate
)
{
this->current_array.push_back(current);
this->action_array.push_back(action);
this->reward_array.push_back(reward);
this->transition_array.push_back(transition);
this->terminate_array.push_back(terminate);
++this->array_size;
this->Sharp(this->sharp_size);
}
void RL::InnerSamples::MakeBatch(const Samples &samples,const int &batch_size)
{
auto ¤t = samples.ReadCurrent();
this->current_array = StateArray(begin(current), begin(current) + batch_size);
auto &action = samples.ReadAction();
this->action_array = ActionArray(begin(action), begin(action) + batch_size);
auto &reward = samples.ReadReward();
this->reward_array = RewardArray(begin(reward), begin(reward) + batch_size);
auto &transition = samples.ReadTransition();
this->transition_array = StateArray(begin(transition), begin(transition) + batch_size);
auto &terminate = samples.ReadTerminate();
this->terminate_array = TerminateArray(begin(terminate), begin(terminate) + batch_size);
this->array_size = batch_size;
}
void RL::InnerSamples::Marge(const Samples & samples)
{
auto inserter = [](auto *this_array, const auto &samples_array)
{
this_array->insert(end(*this_array), begin(samples_array), end(samples_array));
};
inserter(&this->current_array, samples.ReadCurrent());
inserter(&this->action_array, samples.ReadAction());
inserter(&this->transition_array, samples.ReadTransition());
inserter(&this->reward_array, samples.ReadReward());
inserter(&this->terminate_array, samples.ReadTerminate());
this->array_size += samples.ReadArraySize();
this->Sharp(this->sharp_size);
}
void RL::InnerSamples::Clear()
{
this->current_array.clear();
this->action_array.clear();
this->transition_array.clear();
this->reward_array.clear();
this->terminate_array.clear();
this->array_size = 0;
}
► スポイラーを表示
Reader.cpp
[ReadArraySize, ReadCurrent, ReadAction, ReadReward, ReadTransition, ReadTerminate]
[ReadArraySize, ReadCurrent, ReadAction, ReadReward, ReadTransition, ReadTerminate]
#include"InnerSamples.h"
const int & RL::InnerSamples::ReadArraySize() const
{
return this->array_size;
}
const RL::StateArray & RL::InnerSamples::ReadCurrent() const
{
return this->current_array;
}
const RL::ActionArray & RL::InnerSamples::ReadAction() const
{
return this->action_array;
}
const RL::RewardArray & RL::InnerSamples::ReadReward() const
{
return this->reward_array;
}
const RL::StateArray & RL::InnerSamples::ReadTransition() const
{
return this->transition_array;
}
const RL::TerminateArray & RL::InnerSamples::ReadTerminate() const
{
return this->terminate_array;
}
► スポイラーを表示
Setting.cpp
[Constructor, SetSharpSize, Destroy]
[Constructor, SetSharpSize, Destroy]
#include"InnerSamples.h"
RL::InnerSamples::InnerSamples()
:array_size(0)
{
const int default_sharp_size = 1000;
this->SetSharpSize(sharp_size);
}
void RL::InnerSamples::SetSharpSize(const int & sharp_size)
{
this->sharp_size = sharp_size;
}
bool RL::InnerSamples::Destroy()
{
if (this)
{
delete this;
return true;
}
return false;
}
► スポイラーを表示
Sharp.cpp
[Sharp]
こいつだけ algorithm 使うから別ファイル
[Sharp]
#include"InnerSamples.h"
#include
void RL::InnerSamples::Sharp(const int & max_memory)
{
auto pred = [](const double &left, const double &right)
{
auto ret = abs(left) array_size > max_memory)
{
auto itr = std::min_element(begin(reward_array), end(reward_array), pred);
auto dist = std::distance(begin(this->reward_array), itr);
this->current_array.erase(begin(this->current_array) + dist);
this->action_array.erase(begin(this->action_array) + dist);
this->transition_array.erase(begin(this->transition_array) + dist);
this->reward_array.erase(begin(this->reward_array) + dist);
this->terminate_array.erase(begin(this->terminate_array) + dist);
--this->array_size;
}
}
► スポイラーを表示
Shuffle.cpp
[Shuffle]
こいつだけ random 使うから別ファイル
複数の配列を同じルールで並べ替えたかった
(配列aの1と2が入れ替わったら、配列bの1と2も入れ替わる、みたいな)
思いつかなかったからcpprefjpのサイトから std::shuffle の実装例をコピペ
他に頭の良さそうな方法あったら教えてください。
[Shuffle]
#include"InnerSamples.h"
#include
void RL::InnerSamples::Shuffle()
{
//static std::mt19937 mt(std::random_device({})());
static std::mt19937 mt(0);
std::uniform_int_distribution dist;
using param_type = std::uniform_int_distribution::param_type;
for (auto i = 1; i current_array[i], this->current_array[index]);
std::swap(this->action_array[i], this->action_array[index]);
std::swap(this->reward_array[i], this->reward_array[index]);
std::swap(this->transition_array[i], this->transition_array[index]);
std::swap(this->terminate_array[i], this->terminate_array[index]);
}
}
複数の配列を同じルールで並べ替えたかった
(配列aの1と2が入れ替わったら、配列bの1と2も入れ替わる、みたいな)
思いつかなかったからcpprefjpのサイトから std::shuffle の実装例をコピペ
他に頭の良さそうな方法あったら教えてください。
► スポイラーを表示
► スポイラーを表示
Samples.cpp
[GenerateSamples]
本当はstd::unique_ptrを返したかったんです。
でもまたwarningとか出されたら嫌だし、
__interface のデストラクタは継承クラスのデストラクタを呼んでくれないらしいし、
だったら自身を消去する関数が必要だな、と
unique_ptrが保持してるポインタが自分で自分を消したらunique_ptr的には大丈夫なのかちょっとわかんないし、
(カスタムデリータ使えばよくね?)
散々言い訳したけど要は参照型使ってみたかっただけです^p^
[GenerateSamples]
#include "Samples.h"
#include"InnerSamples.h"
RL::Samples& RL::GenerateSamples()
{
return *(new InnerSamples());
}
でもまたwarningとか出されたら嫌だし、
__interface のデストラクタは継承クラスのデストラクタを呼んでくれないらしいし、
だったら自身を消去する関数が必要だな、と
unique_ptrが保持してるポインタが自分で自分を消したらunique_ptr的には大丈夫なのかちょっとわかんないし、
(カスタムデリータ使えばよくね?)
散々言い訳したけど要は参照型使ってみたかっただけです^p^
オフトピック
__interface ではコンストラクタもデストラクタも作れないっぽい。
Initialize関数、Finalize関数を作るのが吉?
Initialize関数、Finalize関数を作るのが吉?
(と何処かのサイトで見た気がします^^;)
今回はインターフェース使ってるし、インナークラスのお陰でカプセル化もできてるし、
これはもしかしてオブジェクト指向的なプログラミングというのができたのでは、、、?
コード載せたお陰で文量がすごいですね^^
ランクアップ間違い無し^p^p^
ツッコミお待ちしております^^