现代CPP设计模式
所有的都是实验品,也有可能是用来对原作者的表达的另一种见解(反驳)。
开闭原则(参考Design pattern in Modern C++ 20):
我的方案吊打原书。面向对象有时候效率极其低下(当然这里只单纯针对filter,如果工程另外一回事)。下面强迫转换成指针为了保证跟原书那个操作一样,filter里面存的是item指针
#include <iostream> #include <vector> #include <ranges>
struct Product{ std::string name{}; int size{}; }; inline constexpr auto tr_items_ptr_fn = [](auto &item){ return &item;}; inline constexpr auto ft_items_size_fn = [](auto size){ return [size](auto *item){ return item->size > size; }; }; int main() { std::vector<Product> items{{"hello",0}, {"world",1}, {"json",2}, {"master",3}}; for(auto *item : items | std::views::transform(tr_items_ptr_fn)| std::views::filter(ft_items_size_fn(1))){ auto &[_n, _s] = *item; std::cout << "name:" << _n << " size:" << _s << std::endl; } return 0; }
输出
name:json size:2 name:master size:3
吐血command模式:
一般command大概interface:
struct ICommand{ virtual void execute() = 0; virtual void undo() = 0; }
今年cppCon讲了一种非常简单的static 模式实现:
Using Modern C++ to Eliminate Virtual Functions - Jonathan Gopel - CppCon 2022
我尝试用了下这个方法做了下static command:
command.ixx
export module command; export template<typename EXEC_FF, typename UNDO_FF> struct command{ EXEC_FF exec; UNDO_FF ff; void execute(){exec();} void undo(){ff();}; }; template<typename T1, typename T2> command(T1, T2)-> command<T1, T2>;
main.cpp
#include <iostream> #include <tuple> #include <vector> import command; template<typename T> concept is_command = requires (T cmd){ {cmd.execute()}-> std::same_as<void>; {cmd.undo()}-> std::same_as<void>; }; template<typename T, typename ... Ts> concept same_as_any = (... or std::same_as<T,Ts>); template<is_command ... command_t> struct commandPool{ template<same_as_any<command_t...> T> auto store(T cmd){ std::get<std::vector<T>>(cmds).emplace_back(cmd); } void execute(){ auto _exec = [](auto & vec_cmd){ for(auto & cmd : vec_cmd){ cmd.execute(); } }; std::apply([this,_exec](auto & ... cmds_list){ (_exec(cmds_list),... ); }, cmds); } void undo(){ auto _exec = [](auto & vec_cmd){ for(auto & cmd : vec_cmd){ cmd.undo(); } }; std::apply([this,_exec](auto & ... cmds_list){ (_exec(cmds_list),... ); }, cmds); } private: std::tuple<std::vector<command_t>...> cmds; }; struct Command2Type{ void execute(){ std::cout << "command 2 type execute\n"; } void undo(){ std::cout << "command 2 type undo\n"; } }; int main() { command cmd{ [](){std::cout << "lambda command execute\n";}, [](){std::cout <<"lambada command undo\n";} }; commandPool<decltype(cmd), Command2Type> cmdPools; cmdPools.store(std::move(cmd)); cmdPools.store(Command2Type()); cmdPools.execute(); cmdPools.undo(); return 0; }
输出:
lambda command execute command 2 type execute lambada command undo command 2 type undo
实际应用中,commandPools设计成软件的单例。把command_type 定义出来,在编译时间确定。