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

news2024/11/18 17:33:43

目录

前言

提问

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.coloradmin.cn/o/1367969.html

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

相关文章

如何下载和处理Sentinel-2数据

Sentinel-2是欧洲空间局&#xff08;ESA&#xff09;Copernicus计划中的一组地球观测卫星&#xff0c;主要用于提供高分辨率的光学遥感数据。Sentinel-2卫星组成了一个多光谱成像系统&#xff0c;可用于监测地球表面的陆地变化、植被覆盖、水域和自然灾害等。它具有以下特性&am…

2019年认证杯SPSSPRO杯数学建模A题(第一阶段)好风凭借力,送我上青云全过程文档及程序

2019年认证杯SPSSPRO杯数学建模 纸飞机在飞行状态下的运动模型 A题 好风凭借力&#xff0c;送我上青云 原题再现&#xff1a; 纸飞机有许多种折法。世界上有若干具有一定影响力的纸飞机比赛&#xff0c;通常的参赛规定是使用一张特定规格的纸&#xff0c;例如 A4 大小的纸张…

java 体育明星管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web 体育明星管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysq…

JQuery异步加载表格选择记录

JQuery异步加载表格选择记录 JQuery操作表格 首先在页面中定义一个表格对象 <table id"insts" class"table"><thead><tr><th>列1</th><th>列2</th><th>例3</th><th></th></tr>…

世微AP2400 DC-DC降压恒流IC12-80V 9V/3A LED电动摩托车灯驱动芯片方案

1&#xff0c;做一款三功能LED车灯驱动方案 AP2400 是一款 PWM 工作模式,率、外围简单、外驱功率管&#xff0c;适用于 输入的降压 LED 恒流驱动芯片。外驱 MOS&#xff0c;大输出电流可达 6A。AP2400 可实现三段功能切换&#xff0c;通过 MODE1/2/3 切换三种功能模式&#xff…

群辉安装gitea

群辉安装gitea 安装giteagitea容器配置 安装gitea gitea容器配置

​安全可靠测评结果公告(2023年第1号)

安全可靠测评主要面向计算机终端和服务器搭载的中央处理器&#xff08;CPU&#xff09;、操作系统以及数据库等基础软硬件产品&#xff0c;通过对产品及其研发单位的核心技术、安全保障、持续发展等方面开展评估&#xff0c;评定产品的安全性和可持续性&#xff0c;实现对产品研…

Opencv实验合集——实验八:相机校准

1.定义 首先&#xff0c;我们来理解一下怎么从相机的角度去看一张图片&#xff0c;就好比如你用眼睛作为相机来进行摄影&#xff0c;但是比摄影机强的是&#xff0c;你是怎么摄影图片之后再将它矫正出现在你眼前&#xff0c;将歪歪扭扭的图片变成一张在你眼前是一张直的图片 为…

孩视宝、飞利浦、书客护眼台灯怎么样?多方位深度测评对比

台灯是我们日常生活中比较常见的一种桌面照明工具&#xff0c;不管是大人用于工作&#xff0c;还是小孩用于学习、阅读&#xff0c;都离不开它。不过我们也要注意&#xff0c;如果使用一款不合格的台灯&#xff0c;时间长了也会影响我们的眼睛健康&#xff0c;尤其是青少年学生…

类别型特征的编码方法

机器学习模型中除了决策树等少数模型能直接处理字符串形式的类别型特征输入外&#xff0c;逻辑回归、支持向量机等模型的输入必须是数值型特征才能在矩阵上执行线性代数计算&#xff0c;所以参加计算的特征必须是数值型的&#xff0c;对于非数值型的特征需要进行编码处理。对于…

【全栈开发|Fresh框架】Fresh环境安装与快速体验Fresh全栈开发

文章目录 前言一、环境配置1. 安装Deno2. 安装idea插件 二、Hello World1.创建项目2.项目结构3. 创建一个路由4. 创建一个动态路由5. 自定义handlers1. 自定义响应头2. 随即生成uuid 6. 表单提交7. 部署到生产环境1. 将代码上传到github2. 在Deno控制面板创建一个项目 总结 前言…

【IEEE会议征稿通知】第五届计算机视觉、图像与深度学习国际学术会议(CVIDL 2024)

第五届计算机视觉、图像与深度学习国际学术会议&#xff08;CVIDL 2024&#xff09; 2024 5th International Conference on Computer Vision, Image and Deep Learning 第五届计算机视觉、图像与深度学习国际学术会议&#xff08;CVIDL 2024&#xff09;定于2024年4月19-21日…

美国成人便携式床护栏ASTMF3186–17安全标准详解

2023年7月21日&#xff0c;美国消费品安全委员会(CPSC)发布了最终规则16CFR1270&#xff0c;建立了成人便携式床栏(APBR)的安全标准&#xff0c;旨在减少与APBR夹住和其他危险相关的不合理的伤害和死亡风险。该规则纳入了ASTMF3186–17&#xff08;成人便携式床栏及相关产品的标…

普冉32位单片机 PY32C642,M0+内核,1.7 V ~ 5.5 V宽工作电压

PY32C642 单片机采用高性能的 32 位 ARM Cortex-M0内核&#xff0c;宽电压工作范围。嵌入 24Kbytes Flash 和 3 Kbytes SRAM 存储器&#xff0c;最高工作频率 24 MHz。包含多种不同封装类型产品。工作温度范围为-40C ~ 85C&#xff0c;工作电压范围 1.7 V ~ 5.5 V。1 路 12 位A…

sketchup 和 solidworks 的区别

两种软件都用过&#xff0c;sketchup 几百兆&#xff0c; solidworks十几个G。 sketchup不愧为草图大师&#xff0c;画立体草图思路简洁&#xff0c;速度很快&#xff0c;总的作图思路是一笔一笔精确的画。我用它设计过很复杂很精确的路灯产品和机械产品&#xff0c;可…

Plotly.js 热力图与折线结合

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

STM32F103GPIO工作模式及原理

目录 GPIO简介GPIO工作模式输入模式输出模式输出速度 GPIO框图和电路解析电路标识电路元件 GPIO工作模式电路解析浮空输入上拉输入下拉输入模拟输入开漏输出推挽输出推挽式复用功能开漏式复用功能 IO工作模式的选取输入模式输出模式 GPIO简介 GPIO&#xff0c;全称为通用输入输…

眼镜用超声波清洗机洗会有伤害吗?这些超声波清洗机适合清洗眼镜

用超声波清洗机洗眼镜是一种非常好的选择&#xff0c;超声波清洗机通过高频振动&#xff0c;将眼镜上的污渍、灰尘等清洗干净&#xff0c;比手洗更彻底、更高效。然而&#xff0c;有些人担心超声波清洗机会对眼镜造成伤害。实际上&#xff0c;这种担心是多余的。超声波清洗机在…

python基础教程八(循环1)

1. while循环 为避免多次重复的代码&#xff0c;我们会用到循环 while (condition): 执行语句 while循环的结构非常简单只要条件满足就一直循环直到&#xff0c;条件不满足为止。 例子如下&#xff1a; x1 while x<100:print(x)x1结果就是最简单的输出1-100的数字 while…

【Internal Server Error】pycharm解决关闭flask端口依然占用问题

Internal Server Error The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. 起因&#xff1a; 我们在运行flask后&#xff0c;断开服务依然保持运行&#xff0…