自由を求めて、戻り値と引数を設定できるFunctionalVisitor
進捗どうですか進捗だめです冬椿です。現実逃避して自由度の高いVisitorパターンを作ってました
ビジターパターンって
void accept(Visitor&visotor)
こんな感じ。自由度がない。戻り値戻せないし引数引けないし。籠のなかの小鳥のよーだ。ドレードレー
奴隷はいやなので色々して自由度の高いビジターパターンを目指してみた。引数も返り値もあるよ。やったね
イメージtemplateとか使ってこうしたい
R accept(Visitor&visotor,T...a)
こうしてみよー
Fuyutsubaki/FunctionalVisitor · GitHub
した
・よくあるディレクトリ構造とFunctionalVisitorのための前処理
using FileVisitor
= FunctionalVisitor<class Files, class Dir, class File>;
struct Files :public FileVisitor::Root{ //Rootを継承するroot
Files(const std::string&name)
:name(name){}
std::string name;
};
//Leafを継承して自身の型を入れるFile
struct File :public FileVisitor::Leaf<File>{
File(const std::string& name, int size)
:base_type(name), size(size){}
int size;
};
//上に同じ
struct Dir :public FileVisitor::Leaf<Dir>{
Dir(const std::string&name, const std::initializer_list<Files*>&list)
:base_type(name), data(list){}
std::vector<Files*>data;
};
で、こんな感じのディレクトリ構造があったとする
auto files = new Dir("新しいフォルダ1", {
new Dir("新しいフォルダ1", { new File("txt.txt", 60), new File("gnp.png", 170) })
, new Dir("新しいフォルダ2", { new File("exe.exe", 20), new File("gpj.jpg", 50) })
});
で、こうじゃ
struct Size{
size_t operator()(const File&file){
return file.size;
}
size_t operator()(const Dir&dir){
size_t sum = 0;
for (auto&x : dir.data)
sum+=FileVisitor::apply_visitor<size_t>(*this,*x);
return sum;
}
};
std::cout << FileVisitor::apply_visitor<size_t>(Size(),*files)<< std::endl;
struct OutPut {
void operator()(const File&file,size_t n){
for (int i = 0; i < n; ++i)
std::cout << '\t';
std::cout <<file.name<<std::endl;
}
void operator()(const Dir&dir, size_t n){
for (int i = 0; i < n; ++i)
std::cout << '\t';
std::cout << dir.name << std::endl;
for (auto&x : dir.data)
FileVisitor::apply_visitor<void>(*this, *x,n+1);
}
};
FileVisitor::apply_visitor<void>(OutPut(), *files, 0);
結果
300
新しいフォルダ1
新しいフォルダ1
txt.txt
gnp.png
新しいフォルダ2
exe.exe
gpj.jpg
いろいろboostのstatic_visitorに似てる。というより真似た。実装は読めなかったけど
なまえこそビジター名乗ってるけどじつはビジターしてない。ダブルディスパってない。でも動作自体はvisitorだしビジターでいいともう