AlgebraMaster

Modern C++ 创造非凡 . 改变世界

导航

现代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 定义出来,在编译时间确定。

posted on 2022-12-11 03:11  gearslogy  阅读(286)  评论(0编辑  收藏  举报