与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>45 enum class ProductType {6     Product1,7     Product28 };910 class Product {11 public:12     virtual ~Product() = default;13     virtual void use() = 0;14 };1516 // Concrete products with different arguments17 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 };2425 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 };3334 // Singleton factory with modern techniques35 class ProductFactory {36 public:37     static ProductFactory& getInstance() {38         static ProductFactory instance;39         return instance;40     }4142     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     }5354 private:55     ProductFactory() = default; // Private constructor for singleton56 };5758 int main() {59     ProductFactory& factory = ProductFactory::getInstance();6061     std::unique_ptr<Product> product1 = factory.createProduct(ProductType::Product1, 42);62     std::unique_ptr<Product> product2 = factory.createProduct(ProductType::Product2, 5, "Hello");6364     product1->use();65     product2->use();6667     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 Product2return 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>45 class Product {6 public:7     virtual ~Product() = default;8     virtual void use() = 0;9 };1011 // Concrete products with different arguments12 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 };1920 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 };2829 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 singleton46 };4748 int main() {49     ProductFactory& factory = ProductFactory::getInstance();5051     std::unique_ptr<Product> product1 = factory.createProduct(42);52     std::string hi("Hello");53     std::unique_ptr<Product> product2 = factory.createProduct(5, hi);5455     product1->use();56     product2->use();5758     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>::typestd::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.hqwc.cn/news/344019.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PaperReading】2. MM-VID

Category Content 论文题目 MM-VID: Advancing Video Understanding with GPT-4V(ision) 作者 Kevin Lin, Faisal Ahmed, Linjie Li, Chung-Ching Lin, Ehsan Azarnasab, Zhengyuan Yang, Jianfeng Wang, Lin Liang, Zicheng Liu, Yumao Lu, Ce Liu, Lijuan Wang (Microso…

蚂蚁爱购--靠谱的SpringBoot项目

简介 这是一个靠谱的SpringBoot项目实战&#xff0c;名字叫蚂蚁爱购。从零开发项目&#xff0c;视频加文档&#xff0c;十天就能学会开发JavaWeb项目。 教程路线是&#xff1a;搭建环境> 安装软件> 创建项目> 添加依赖和配置> 通过表生成代码> 编写Java代码&g…

Spring Boot - Application Events 的发布顺序_ApplicationPreparedEvent

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c;它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦&#…

统计学-R语言-3

文章目录 前言给直方图增加正态曲线的不恰当之处直方图与条形图的区别核密度图时间序列图洛伦茨曲线计算绘制洛伦茨曲线所需的各百分比数值绘制洛伦茨曲线 练习 前言 本篇文章是介绍对数据的部分图形可视化的图型展现。 给直方图增加正态曲线的不恰当之处 需要注意的是&#…

【生产者消费者模型的 Java 实现】

文章目录 前言传统派维新派 前言 题目&#xff1a;一个初始值为零的变量&#xff0c;多个线程对其交替操作&#xff0c;分别加1减1 实现步骤&#xff1a; 线程操作资源类判断&#xff0c;干活&#xff0c;通知防止虚假唤醒机制&#xff0c;即&#xff1a;多线程的判断需要用…

PostMan、LoadRunner进行并发压测流程

需求 两个记账接口在同一时间大量处理同一账户账务时&#xff0c;锁表顺序不同导致死锁&#xff0c;在修改完代码后模拟生产记账流程进行测试&#xff0c;需要对两个接口进行并发测试。 在进行压测的时候&#xff0c;需要对流水号进行递增。 PostMan处理流程 1. 新建Collection…

Qt QComboBox组合框控件

文章目录 1 属性和方法1.1 文本1.2 图标1.3 插入和删除1.4 信号和槽 2 实例2.1 布局2.2 代码实现 Qt中的组合框是集按钮和下拉列表体的控件&#xff0c;&#xff0c;它占用的屏幕空间很小&#xff0c;对应的类是QComboBox 1 属性和方法 QComboBox有很多属性&#xff0c;完整的…

html代码

1、Echart各种图表示例 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>ECharts 箱线图示例</title> <!-- 引入 ECharts 文件 --> <script src"https://cdn.jsdelivr.net/npm/ech…

CRLF漏洞靶场记录

搭建 利用 docker 搭建 vulhub 靶场 git clone https://github.com/vulhub/vulhub.git 进入 /vulhub/nginx/insecure-configuration 目录 启动前关闭现有的 8080、8081、8082 端口服务&#xff0c;避免端口占用 docker-compose up -d 进入容器 docker exec -it insecure-…

Invalid bound statement(只有调用IService接口这一层会报错的)

问题描述:controller直接调用实现类可以,但是一旦调用IService这个接口这一层就报错. 找遍了大家都说是xml没对应好,但是我确实都可以一路往下跳,真的对应好了.结果发现是 MapperScan写错了,如下才是对的. MapperScan的作用是不需要在mapper上一直写注解了,只要启动类上写好就放…

统一格式,无限创意:高效管理不同格式图片批量转换

在数字时代&#xff0c;图片格式的多样性带来了管理上的不便。为了满足不同的需求&#xff0c;我们经常需要将大量图片转换为统一的格式。那么&#xff0c;有没有一种简单、高效的方法来解决这个问题呢&#xff1f;答案是肯定的&#xff01;今天&#xff0c;我们将为您介绍一款…

档案数字化怎样快速整理资料

对于机构和组织来说&#xff0c;档案数字化是一个重要的信息管理和保护措施。要快速整理资料进行档案数字化&#xff0c;可以遵循以下步骤&#xff1a; 1. 准备工具和设备&#xff1a;确保有一台计算机、扫描仪和相关软件。 2. 分类和组织资料&#xff1a;先将资料分类&#xf…