与AI合作 -- 写一个modern c++单例工厂

目录

前言

提问

bard给出的答案

AI答案的问题

要求bard改进

 人类智能

AI VS 人类


前言

通过本文读者可以学到modern C++单例模式+工厂模式的混合体,同时也能看到:如今AI发展到了怎样的智能程度?怎样让AI帮助我们快速完成实现头脑中的想法?以及这样的智能程度会不会让程序员失业?

提问

这次我不用ChatGPT了,而是换成了bard.

mzhai: Write a Modern c++ program to implement a singleton factory to produce 2 products. Each product has different arguments, the 1st has only one parameter of type int, the 2nd product has two parameters int and string respectively.

 这里我特意提出要创建两个参数不同的产品,防止AI写出来的类不通用(有点像避免算法过拟合的感觉)。

bard给出的答案

  1 #include <iostream>
  2 #include <memory>
  3 #include <utility>
  4
  5 enum class ProductType {
  6     Product1,
  7     Product2
  8 };
  9
 10 class Product {
 11 public:
 12     virtual ~Product() = default;
 13     virtual void use() = 0;
 14 };
 15
 16 // Concrete products with different arguments
 17 class Product1 : public Product {
 18 public:
 19     Product1(int arg1) : arg1_(arg1) {}
 20     void use() override { std::cout << "Using Product1 with arg1: " << arg1_ << std::endl; }
 21 private:
 22     int arg1_;
 23 };
 24
 25 class Product2 : public Product {
 26 public:
 27     Product2(int arg2_1, std::string arg2_2) : arg2_1_(arg2_1), arg2_2_(arg2_2) {}
 28     void use() override { std::cout << "Using Product2 with arg2_1: " << arg2_1_ << ", arg2_2: " << arg2_2_ << std::endl;     }
 29 private:
 30     int arg2_1_;
 31     std::string arg2_2_;
 32 };
 33
 34 // Singleton factory with modern techniques
 35 class ProductFactory {
 36 public:
 37     static ProductFactory& getInstance() {
 38         static ProductFactory instance;
 39         return instance;
 40     }
 41
 42     template <typename... Args>
 43     std::unique_ptr<Product> createProduct(ProductType type, Args&&... args) {
 44         switch (type) {
 45             case ProductType::Product1:
 46                 return std::make_unique<Product1>(std::forward<Args>(args)...);
 47             case ProductType::Product2:
 48                 return std::make_unique<Product2>(std::forward<Args>(args)...);
 49             default:
 50                 throw std::invalid_argument("Invalid product type");
 51         }
 52     }
 53
 54 private:
 55     ProductFactory() = default; // Private constructor for singleton
 56 };
 57
 58 int main() {
 59     ProductFactory& factory = ProductFactory::getInstance();
 60
 61     std::unique_ptr<Product> product1 = factory.createProduct(ProductType::Product1, 42);
 62     std::unique_ptr<Product> product2 = factory.createProduct(ProductType::Product2, 5, "Hello");
 63
 64     product1->use();
 65     product2->use();
 66
 67     return 0;
 68 }

AI答案的问题

第一次给出的答案编译失败,报错信息如下

/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/unique_ptr.h:1065:34: error: no matching constructor for initialization of 'Product2'
 1065 |     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
      |                                  ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/insights/insights.cpp:48:29: note: in instantiation of function template specialization 'std::make_unique<Product2, int>' requested here
   48 |                 return std::make_unique<Product2>(std::forward<Args>(args)...);
      |                             ^

有点奇怪吧,62行我们明明给Product2传的是两个参数,不是有Product2才走case ProductType::Product2吗(48行)?但编译器却抱怨给Product2的构造函数只传了一个int。这是为什么哪?

这是因为case是运行时代码,而createProduct根据61、62行会产生两个重载,每个都包含全部代码。比如61行会产生如下code:

std::unique_ptr<Product> createProduct(ProductType type, int arg) {
    switch (type) {
        case ProductType::Product1:
            return std::make_unique<Product1>(arg);
        case ProductType::Product2:
            return std::make_unique<Product2>(arg);
        default:
            throw std::invalid_argument("Invalid product type");
    }
}

因为Product2的构造函数有两个参数,而此处只有一个(int arg), 故找不到匹配的构造函数。

要求bard改进

直接把错误贴给他,它还是没能正真理解编译失败的原因,之所以这么说,是因为它给出的解决方案是:

case ProductType::Product2:
                if constexpr (sizeof...(Args) == 2) { // Ensure 2 arguments for Product2
                    return std::make_unique<Product2>(std::forward<Args>(args)...);
                } else {
                    throw std::invalid_argument("Invalid arguments for Product2");
                }

 constexpr (sizeof...(Args) == 2) 确实在编译阶段就判断除了TRUE/FALSE:如果条件不符合,这段代码就不走了,从而导致61行实例出来的createProduct函数不报错,但62行依然会报错(看后面的cppinsights截图就会明白了)。我们暂且按照这种思路试一试, 虽然它有问题(后面会说)。

  1 #include <iostream>
  2 #include <memory>
  3 #include <utility>
  4
  5 class Product {
  6 public:
  7     virtual ~Product() = default;
  8     virtual void use() = 0;
  9 };
 10
 11 // Concrete products with different arguments
 12 class Product1 : public Product {
 13 public:
 14     Product1(int arg1) : arg1_(arg1) {}
 15     void use() override { std::cout << "Using Product1 with arg1: " << arg1_ << std::endl; }
 16 private:
 17     int arg1_;
 18 };
 19
 20 class Product2 : public Product {
 21 public:
 22     Product2(int arg2_1, std::string arg2_2) : arg2_1_(arg2_1), arg2_2_(arg2_2) {}
 23     void use() override { std::cout << "Using Product2 with arg2_1: " << arg2_1_ << ", arg2_2: " << arg2_2_ << std::endl;     }
 24 private:
 25     int arg2_1_;
 26     std::string arg2_2_;
 27 };
 28
 29 class ProductFactory {
 30 public:
 31     static ProductFactory& getInstance() {
 32         static ProductFactory instance;
 33         return instance;
 34     }
 35     template <typename... Args>
 36     std::unique_ptr<Product> createProduct(Args&&... args) {
 37         if constexpr (sizeof...(Args) == 1){
 38             return std::make_unique<Product1>(std::forward<Args>(args)...);
 39         }
 40         if constexpr (sizeof...(Args) == 2){
 41             return std::make_unique<Product2>(std::forward<Args>(args)...);
 42         }
 43     }
 44 private:
 45     ProductFactory() = default; // Private constructor for singleton
 46 };
 47
 48 int main() {
 49     ProductFactory& factory = ProductFactory::getInstance();
 50
 51     std::unique_ptr<Product> product1 = factory.createProduct(42);
 52     std::string hi("Hello");
 53     std::unique_ptr<Product> product2 = factory.createProduct(5, hi);
 54
 55     product1->use();
 56     product2->use();
 57
 58     return 0;
 59 }

编译成功,运行也没问题。我们还可以通过cppinsights.io看看模板函数实例化出来的2个重载结果:

 显然这种办法不好:

  1. 请想一想如果product1 和Product2都只有一个参数哪?就无法通过sizeof区分了。
  2. 而且,这么做产生了很多无用代码(if constexpr...)

人类智能

所以还是由我给它快速改一改吧。我们直接给createProduct函数多传一个模板参数进去,比如叫T,像下面这样:

template <typename T, typename... Args>
std::unique_ptr<T> createProduct(Args&&... args) {
    return std::make_unique<T>(std::forward<Args>(args)...);
}

...

std::unique_ptr<Product> product1 = factory.createProduct<Product1>(42);
std::string hi("Hello");
std::unique_ptr<Product> product2 = factory.createProduct<Product2>(5, hi);

看下createProduct如何实例化的?

 问一下bard这么改怎么样?回答的井井有条!

mzhai:How about changing the code to above?

Bard: I'm happy to review the proposed code changes:

Key Changes:

  • Templated createProduct function: The createProduct function now takes a template parameter T to specify the product type, eliminating the need for the ProductType enum. (传了T就没必要传ProductType enum了)
  • Removal of switch statement: The switch statement is no longer needed as the compiler determines the correct type based on the template argument.(createProduct中的Switch可以去掉了)
  • Explicit product type in main: The createProduct function is called with explicit template arguments (Product1 and Product2) to create the desired product types.(main中要显示指定产品类型,即尖括号中的Product1、Product2)

Analysis:

  • Pros:
    • More concise and less verbose code. (代码简明)
    • Leverages template metaprogramming for type-driven behavior.(利用了模板元编程)
    • Potentially easier to extend for new product types.(新产品类型扩展更容易)
  • Cons:
    • Might be less readable for those less familiar with templates.(对不熟悉模板的人来说可读性变差)
    • Error messages might be more cryptic due to template instantiation.(因为模板实例导致报错信息比较神秘不那么直接,确实!)
    • Doesn't enforce a closed set of product types (could potentially create other types).(没有强制指定哪些产品类型能生产,有产生别的类型的风险)

Overall:

  • The changes are valid and adhere to modern C++ practices.
  • The choice between this approach and the previous one using the ProductType enum is mainly a matter of preference and trade-offs.
  • Consider the team's familiarity with templates and the specific project requirements when deciding on the best approach.

Additional Notes:

  • Ensure that all product classes (Product1Product2, etc.) are derived from the Product base class for this approach to work correctly.
  • Consider using static_assert or concepts (if available in your C++ version) to enforce constraints on the template parameter T, ensuring it's a valid product type.

AI VS 人类

AI确实智商还有限,但也确实能提高编程效率,copilot等等一般宣传能提高人类编程效率50%左右,在没有增量就业机会的情况下也就是一半工程师要失业了?? 

附上最终代码

便于大家COPY及实验。

#include <iostream>
#include <memory>
#include <utility>

class Product {
public:
    virtual ~Product() = default;
    virtual void use() = 0;
};

// Concrete products with different arguments
class Product1 : public Product {
public:
    Product1(int arg1) : arg1_(arg1) {}
    void use() override { std::cout << "Using Product1 with arg1: " << arg1_ << std::endl; }
private:
    int arg1_;
};

class Product2 : public Product {
public:
    Product2(int arg2_1, std::string arg2_2) : arg2_1_(arg2_1), arg2_2_(arg2_2) {}
    void use() override { std::cout << "Using Product2 with arg2_1: " << arg2_1_ << ", arg2_2: " << arg2_2_ << std::endl; }
private:
    int arg2_1_;
    std::string arg2_2_;
};

class ProductFactory {
public:
    static ProductFactory& getInstance() {
        static ProductFactory instance;
        return instance;
    }

    template <typename T, typename... Args>
    //typename std::enable_if<std::is_same<Product,T>::value, void>::type
    std::unique_ptr<T> createProduct(Args&&... args) {
        return std::make_unique<T>(std::forward<Args>(args)...);
    }

private:
    ProductFactory() = default; // Private constructor for singleton
};

int main() {
    ProductFactory factory;

    std::unique_ptr<Product> product1 = factory.createProduct<Product1>(42);
    std::string hi("Hello");
    std::unique_ptr<Product> product2 = factory.createProduct<Product2>(5, hi);

    product1->use();
    product2->use();

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/304012.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【hcie-cloud】【17】华为云Stack灾备服务介绍【灾备方案概述、备份解决方案介绍】【上】

文章目录 前言灾备方案概述灾备的定义灾备的重要性故障和灾难对业务连续性带来的挑战灾备系统的衡量指标RTO与RPO分析 灾备等级标准数据中心容灾解决方案全景图云灾备服务总结架构华为云Stack灾备服务总览 备份解决方案介绍云备份服务介绍备份服务架构介绍云备份服务组件功能介…

界面原型设计工具有哪些?看看这9个

界面原型设计是现代设计师必备的技能之一。在设计数字产品或应用程序时&#xff0c;界面原型是将概念转化为具体可交互界面的重要步骤。对于新手小白来说&#xff0c;选择一款易于上手且功能强大的界面原型设计工具至关重要。本文将介绍 9 个常用的界面原型设计工具&#xff0c…

计算机体系结构动态调度(计分板及Tomasulo)学习记录

1.动态调度核心思想&#xff1a;允许就绪指令越过前方停顿指令&#xff0c;提前进入运行&#xff08;乱序执行&#xff09; 就绪指令指不存在资源冲突、操作数已就绪的指令&#xff0c;例如&#xff0c;计分板算法使用计分板来实现&#xff0c;Tomasulo使用保留站来实现&#…

苹果电脑交互式原型设计软件Axure RP 9 mac特色介绍

Axure RP 9 for Mac是一款交互式原型设计软件&#xff0c;使用axure rp9以最佳的方式展示您的作品&#xff0c;优化现代浏览器并为现代工作流程设计。同时确保您的解决方案正确完整地构建。Axure RP 9 for Mac为您整理笔记&#xff0c;将其分配给UI元素&#xff0c;并合并屏幕注…

swing快速入门(三十九)进度对话框

&#x1f381;注释很详细&#xff0c;直接上代码 上一篇 &#x1f9e7;新增内容 &#x1f9e8;1.模拟耗时操作 &#x1f9e8;2.使用计时器更新进度对话框 &#x1f380;源码&#xff1a; package swing31_40;import javax.swing.*; import java.awt.event.ActionEvent; import …

【debug】为什么ansible中使用command出错

碎碎念 在使用ansible执行command的时候&#xff0c;遇到执行会出错的command 比如执行source打算读取环境变量的时候 错误提示为&#xff1a; 没有那个文件或目录:source 一开始以为是错误提示有问题&#xff0c;一直在testrc的路径上检查&#xff0c;但是同样一行命令使用…

C++八股学习心得.8

1.const知道吗&#xff1f;解释其作用 const 修饰类的成员变量&#xff0c;表示成员常量&#xff0c;不能被修改。 const修饰函数承诺在本函数内部不会修改类内的数据成员&#xff0c;不会调用其它非 const 成员函数。 如果 const 构成函数重载&#xff0c;const 对象只能调…

聊聊 Java 集合框架中的 ArrayList

其实 Java 集合框架也叫做容器&#xff0c;主要由两大接口派生而来&#xff0c;一个是 collection,主要存放对象的集合。另外一个是Map, 存储着键值对&#xff08;两个对象&#xff09;的映射表。 下面就来说说 List接口&#xff0c;List存储的元素是有序、可重复的。其下有三个…

配置git服务器

第一步&#xff1a; jdk环境配置 &#xff08;1&#xff09;搜索【高级系统设置】&#xff0c;选择【高级】选项卡&#xff0c;点【环境变量】 &#xff08;2&#xff09;在【系统变量】里面&#xff0c;点击【新建】 &#xff08;3&#xff09;添加JAVA_HOME环境变量JAVA_HO…

展台搭建的基本要求

一、选址及总平面布置 展厅人流量大&#xff0c;对选址和总平面布置的要求如下:展厅选址应位于市内或郊区交通便利的区域。大型展览馆应有足够的群众活动广场和停车面积 &#xff0c;并应有室外陈列场地。室外场地要考虑环境的绿化和美化。各功能分区之间联系方便又互不干扰。建…

实现LCM在docker之间的通信

目录 1.docker容器互联 新建网络 连接容器 2.设置环境变量 3.在两个docker之间实现通信 1.docker容器互联 新建网络 $ docker network create -d bridge test-net 连接容器 运行一个容器并连接到新建的 test-net 网络: $ docker run -itd --name lcm_1 --network tes…

极智项目 | 实战Paddle戴口罩检测

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多项目分享 大家好&#xff0c;我是极智视界&#xff0c;本文来介绍 实战 Paddle 戴口罩检测项目。 本文介绍的 实战 Paddle 戴口罩检测项目&#xff0c;提供完整的可以一键执行的项目工程源码&#xff0c;获取方式有两个…

AI红娘开启约会新时代;网易云音乐Agent实践探索;微软生成式AI课程要点笔记;ComfyUI新手教程;图解RAG进阶技术 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f440; Perplexity 官宣 7360 万美元B轮融资&#xff0c;打造世界上最快最准确的答案平台 https://blog.perplexity.ai/blog/perplexity-rais…

yyds,4 个 Pandas 必备神器!

Pandas是我们日常处理表格数据最常用的包&#xff0c;但是对于数据分析来说&#xff0c;Pandas的DataFrame还不够直观。 今天我们将介绍4个和Pandas相关的Python包&#xff0c;可以将Pandas的DataFrame转换交互式表格&#xff0c;让我们可以直接在上面进行数据分析的操作。 P…

天洑软件与常州大学成立电子信息专业学位硕士研究生联合培养基地

2023年12月27日&#xff0c;天洑软件与常州大学微电子与控制工程学院成立电子信息专业学位硕士研究生联合培养基地&#xff0c;授牌及企业导师聘任仪式于常州大学西太湖校区隆重举办。天洑软件前瞻技术研究院院长张儒受邀与会。 开幕式上&#xff0c;微电子与控制工程学院党委书…

NUXT3学习笔记

1.邂逅SPA、SSR 1.1 单页面应用程序 单页应用程序 (SPA) 全称是&#xff1a;Single-page application&#xff0c;SPA应用是在客户端呈现的&#xff08;术语称&#xff1a;CSR&#xff08;Client Side Render&#xff09;&#xff09; SPA的优点 只需加载一次 SPA应用程序只需…

Docker实战08|Docker管道及环境变量识别

上一篇文章中&#xff0c;讲解了如何通过Go语言实现对Docker Cgroup的资源限制 具体文章可见《Docker就应该这么学-07》 有需要的小伙伴可以回顾一下。 接下来本文会详细介绍一下Docker 管道及环境变量识别 管道及环境变量识别 获取代码 git clone https://gitee.com/mjr…

SEO全自动发布外链工具源码系统:自动增加权重 附带完整的搭建安装教程

SEO全自动发布外链工具是一款基于PHP和MySQL开发的外链发布工具。它通过自动化流程&#xff0c;帮助站长快速、有效地发布外链&#xff0c;提高网站的权重和排名。该工具支持多种外链发布平台&#xff0c;如论坛、博客、分类信息等&#xff0c;可自定义发布内容和格式&#xff…

Plotly.js 热力图与折线结合

上次记录了Echarts热力图与折线图的结合&#xff0c;但其效果不是很自然。后又找到了Plotly.js库&#xff0c;发现其效果不错。在此整理下实现过程。这里面涉及到自定义工具栏、自定义工具图标等等 配置工具栏显示的工具图标 let config {locale: zh-cn, // 设置本地语…

代码随想录刷题第四十三天| 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零

代码随想录刷题第四十三天 今天为三道0-1背包问题的变种&#xff0c; 分别有三个小问题 给定一个容量为j的背包&#xff0c;尽可能装下物品&#xff0c;找到能装下物品的最大价值 dp[i][j] max(dp[i-1][j], dp[i-1][j-nums[i]]nums[i]) 给定一个容量为j的背包&#xff0c;找…