与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.mzph.cn/news/607166.shtml

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

相关文章

【Linux】Ubuntu 22.04 上安装最新版 Nextcloud Hub 7 (28.0.1)

在 Ubuntu 22.04 上安装 PHP 版本 安装多个 PHP 版本的最简单方法是使用来自 Debian 开发人员 Ondřej Sur 的 PPA。要添加此 PPA,请在终端中运行以下命令。如果要从 PPA 安装软件,则需要 software-properties-common 包。它会自动安装在 Ubuntu 桌面上,但可能会在您的 Ubuntu…

进阶分布式链路追踪

另外我的新书RocketMQ消息中间件实战派上下册&#xff0c;在京东已经上架啦&#xff0c;目前都是5折&#xff0c;非常的实惠。 https://item.jd.com/14337086.html​编辑https://item.jd.com/14337086.html “RocketMQ消息中间件实战派上下册”是我既“Spring Cloud Alibaba微…

读元宇宙改变一切笔记03_元素(下)

1. 元素2&#xff1a;3D&#xff0c;互联网的下一个伟大迈进 1.1. 3D的必要性不仅仅是因为它预示着新事物的出现 1.1.1. 为了使人类文化和劳动实现从物理世界向数字世界的过渡&#xff0c;必须借助3D环境 1.2. 用户通过几乎源源不断的高分辨…

JVM工作原理与实战(十):类加载器-Java类加载器

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、介绍 二、扩展类加载器 三、通过扩展类加载器去加载用户jar包 1.放入/jre/lib/ext下进行扩展 2.使用参数进行扩展 四、应用程序类加载器 总结 前言 ​JVM作为Java程序的运行…

LeetCode 每日一题 2024/1/1-2024/1/7

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 1/1 1599. 经营摩天轮的最大利润1/2 466. 统计重复个数1/3 2487. 从链表中移除节点1/4 2397. 被列覆盖的最多行数1/5 1944. 队列中可以看到的人数1/6 2807. 在链表中插入最…

Python——运算符

num 1 num 1 print("num1:", num) num - 1 print("num-1:", num) num * 4 print("num*4:", num) num / 4 print("num/4:", num) num 3 num % 2 print("num%2:", num) num ** 2 print("num**2:", num) 运行结果…

实验五:动态路由配置

实验五&#xff1a;动态路由配置 1.RIP 配置 【实验名称】 RIP 路由协议配置 【实验目的】掌握路由器 RIP 路由协议的基本配置 【实验设备】路由器&#xff08; 2 台&#xff09;、计算机&#xff08; 2 台&#xff09;、配置电缆&#xff08; 1 根&#xff09;、 V…

【Linux Shell】10. 函数

文章目录 【 1. 函数的定义 】【 2. 函数参数 】 【 1. 函数的定义 】 所有函数在使用前必须定义 。这意味着必须将函数放在脚本开始部分&#xff0c;直至shell解释器首次发现它时&#xff0c;才可以使用。 调用函数仅使用其函数名即可 。 函数返回值在调用该函数后通过 $? 来…

laravel getQueryLog() time 代表什么

laravel中的getQueryLog()方法返回了执行的所有查询的详细信息&#xff0c;包括查询语句、绑定的参数和查询的执行时间等。其中&#xff0c;time字段代表了每个查询的执行时间&#xff0c;以毫秒为单位。 以下是一个示例代码&#xff0c;演示了如何使用getQueryLog()方法获取查…

我的阿里云服务器被攻击了

服务器被DDoS攻击最恶心&#xff0c;尤其是阿里云的服务器受攻击最频繁&#xff0c;因为黑客都知道阿里云服务器防御低&#xff0c;一但被攻击就会进入黑洞清洗&#xff0c;轻的IP停止半小时&#xff0c;重的停两个至24小时&#xff0c;给网站带来很严重的损失。而处理 ddos 攻…

华为ipv4+ipv6双栈加isis多拓扑配置案例

实现效果&#xff1a;sw1中的ipv4和ipv6地址能ping通sw2中的ipv4和ipv6地址 R2-R4为存IPV4连接&#xff0c;其它为ipv6和ipv4双连接 sw1 ipv6 interface Vlanif1 ipv6 enable ip address 10.0.11.1 255.255.255.0 ipv6 address 2001:DB8:11::1/64 interface MEth0/0/1 inter…

AIGC(MLLM、VLM、LLM、SD)系列——论文解读目录

涉及面广:多模态生成模型——MLLM ( 目前集中在视觉语言模型——VLM)、大语言模型——LLM、生成模型(SD系列)、对比学习的经典模型(CLIP系列)。 持续更新:对于已经完成解读的会附上链接(有的会在一些场景做尝试,也会附上链接供大家快速参考结果),准备写的会备注筹…

K8S学习指南(70)-K8S中的informa机制

引言 在 Kubernetes 集群中&#xff0c;Informer 是一种重要的机制&#xff0c;用于监控和处理集群中资源对象的变化。它是基于观察者模式设计的&#xff0c;允许开发者注册对某类资源对象的关注&#xff0c;并在对象发生变化时得到通知。本文将深入介绍 Kubernetes 中的 Info…

Pytorch:torch.nn.Module

torch.nn.Module 是 PyTorch 中神经网络模型的基类&#xff0c;它提供了模型定义、参数管理和其他相关功能。 以下是关于 torch.nn.Module 的详细说明&#xff1a; 1. torch.nn.Module 的定义&#xff1a; torch.nn.Module 是 PyTorch 中所有神经网络模型的基类&#xff0c;…

Java课程设计团队博客 —— 基于网页的时间管理系统

博客目录 1.项目简介2.项目采用的技术3.功能需求分析4.项目亮点5.主要功能截图6.Git地址7.总结 Java团队博客分工 姓名职务负责模块个人博客孙岚组长 资源文件路径和tomcat服务器的相关配置。 前端的页面设计与逻辑实现的代码编写。 Servlet前后端数据交互的编写。 用户登录和…

java Servlet体育馆运营管理系统myeclipse开发mysql数据库网页mvc模式java编程计算机网页设计

一、源码特点 JSP 体育馆运营管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统采用serlvetdaobean&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用 B/S模式开发。 java Servlet体育馆运营管理系…

嵌入式培训机构四个月实训课程笔记(完整版)-Linux系统编程第六天-Linux信号(物联技术666)

更多配套资料CSDN地址:点赞+关注,功德无量。更多配套资料,欢迎私信。 物联技术666_嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记-CSDN博客物联技术666擅长嵌入式C语言开发,嵌入式硬件,嵌入式培训笔记,等方面的知识,物联技术666关注机器学习,arm开发,物联网,嵌入式硬件,单片机…

910b上跑Chatglm3-6b进行流式输出【pytorch框架】

文章目录 准备阶段避坑阶段添加代码结果展示 准备阶段 配套软件包Ascend-cann-toolkit和Ascend-cann-nnae适配昇腾的Pytorch适配昇腾的Torchvision Adapter下载ChatGLM3代码下载chatglm3-6b模型&#xff0c;或在modelscope里下载 避坑阶段 每个人的服务器都不一样&#xff0…

vue3 封装一个Tooltip 文字提示组件

效果图 默认展示icon图标&#xff0c;悬浮展示文字 如果slot有内容则展示对应内容 实现 用的是El-Tooltip组件 Element - The worlds most popular Vue UI framework 组件代码 <script setup lang"ts"> import { Icon } from /components/Icon import { ElTo…

Linux set命令教程:如何优雅地设置和取消shell变量和选项(附实例详解和注意事项)

Linux set命令介绍 set命令是Linux操作系统中的内置shell命令&#xff0c;用于设置和取消shell变量和选项。它常用于shell脚本中&#xff0c;以配置环境并控制脚本的行为。 Linux set命令适用的Linux版本 set命令在所有主流的Linux发行版中都可以使用&#xff0c;包括但不限…