楼主: 已注销-2317
跳转到指定楼层
上一主题 下一主题
收起左侧

吐槽一下c++

🔗
Airtnp 2019-5-21 17:39:02 | 只看该作者
全局:
另外一个可能有点卵用的写法:
http://www.open-std.org/jtc1/sc2 ... s/2016/p0195r2.html
回复

使用道具 举报

🔗
magicsets 2019-5-22 00:10:06 | 只看该作者
全局:
Airtnp 发表于 2019-5-21 17:34
这个其实就是std::variant... https://en.cppreference.com/w/cpp/utility/variant/variant

是说TypeList像std::variant么.. 我觉得完全不是一回事啊,首先那一堆做类型推导的meta functions和variant一点关系没有,你拿variant过来是没法使用std::is_constructible进行过滤以及条件性给出编译时错误的。

std::variant本质上就是一个功能有限的tagged union,顶多是ForEach那边“看起来有点像”搭配std::variant使用的std::visit —— 但也有很大的区别,因为std::visit是要拿对应类型的instance来dispatch的,而我们这里是根据运行时一个string的值(也就是"name"参数)进行dispatch,这个相关机制必须手写:要么用TypeList这个比较强大的工具,要么手写一个template recursive function。

当然这只是我的理解,如果你有什么巧妙的想法不妨试着实现一下,如果只是引用一两个概念别人可能没有办法理解你的方案,而且去实现一下自己才能知道是否行得通。
回复

使用道具 举报

🔗
 楼主| 已注销-2317 2019-5-22 01:44:22 | 只看该作者
全局:
magicsets 发表于 2019-5-21 16:36
第一个问题要带类型检查的话其实非常麻烦,因为需要在编译期做很多事情,我写了一份参考代码,测试环境用的 ...

多谢大佬解答问题!
代码有些复杂,我要研究一下
回复

使用道具 举报

🔗
Airtnp 2019-5-22 13:55:53 | 只看该作者
全局:
magicsets 发表于 2019-5-22 00:10
是说TypeList像std::variant么.. 我觉得完全不是一回事啊,首先那一堆做类型推导的meta functions和varia ...

https://wandbox.org/permlink/soNyHbuhPkiz9nJg

我傻了。。。因为visit也是用笛卡尔积实现的

写了三种
回复

使用道具 举报

🔗
magicsets 2019-5-23 12:53:13 | 只看该作者
全局:
Airtnp 发表于 2019-5-22 13:55
https://wandbox.org/permlink/soNyHbuhPkiz9nJg

我傻了。。。因为visit也是用笛卡尔积实现的

写得不错~ 其实可以看出来能work的还是只有第一种编译时枚举的方法

第二种方法(使用typeinfo)没有办法做隐式类型转换,而且想要把general的隐式类型转换在runtime做应该也是不可能的

第三种方法要求所有的create()具有不同的signature,这个方法甚至都没有使用name变量.. instantiate错了也是不能检查出来的

回复

使用道具 举报

🔗
biuss2 2019-6-3 22:05:30 | 只看该作者
全局:
最近也在巩固C++,感觉东西真的挺多的。看着看着就有点晕了
回复

使用道具 举报

🔗
feitao 2019-6-15 14:41:51 | 只看该作者
全局:
本帖最后由 feitao 于 2019-6-15 14:56 编辑

根据下面的网址改编:

  1. /// [url]https://stackoverflow.com/a/29154449[/url]
  2. /// [url]https://wandbox.org/permlink/wghDJw5xbDHVZ52x[/url]

  3. #include <iostream>
  4. #include <memory>
  5. #include <stdexcept>
  6. #include <string>
  7. #include <unordered_map>
  8. #include <utility>

  9. #include <gtest/gtest.h>

  10. using namespace std::string_literals;

  11. struct Base {
  12.     virtual ~Base() = 0;
  13. };

  14. Base::~Base() {}

  15. template <typename... Args>
  16. class Factory {
  17. public:
  18.     static Factory& get()
  19.     {
  20.         static Factory instance;
  21.         return instance;
  22.     }

  23.     template <typename T>
  24.     void reg(const std::string& name)
  25.     {
  26.         auto it = stock.find(name);
  27.         if (it != stock.end()) {
  28.             throw std::invalid_argument(name + " has been registered: " + __PRETTY_FUNCTION__);
  29.         }
  30.         stock[name].reset(new Creator<T>);
  31.     }

  32.     std::unique_ptr<Base> create(const std::string& name, Args&&... args)
  33.     {
  34.         auto it = stock.find(name);
  35.         if (it == stock.end()) {
  36.             throw std::invalid_argument("Cannot find "s + __PRETTY_FUNCTION__);
  37.             // std::cout << "Cannot find " << __PRETTY_FUNCTION__ << '\n';
  38.             // return nullptr;
  39.         }
  40.         std::cout << __PRETTY_FUNCTION__ << '\n';
  41.         return it->second->create(std::forward<Args>(args)...);
  42.     }

  43. private:
  44.     struct ICreator {
  45.         virtual std::unique_ptr<Base> create(Args&&...) = 0;
  46.         virtual ~ICreator() = default;
  47.     };

  48.     template <typename T>
  49.     struct Creator : public ICreator {
  50.         virtual std::unique_ptr<Base> create(Args&&... args) override
  51.         {
  52.             return std::make_unique<T>(std::forward<Args>(args)...);
  53.         }
  54.     };

  55.     std::unordered_map<std::string, std::unique_ptr<ICreator>> stock;
  56. };

  57. template <typename... Args>
  58. std::unique_ptr<Base> create(const std::string& name, Args&&... args)
  59. {
  60.     return Factory<Args...>::get().create(name, std::forward<Args>(args)...);
  61. }

  62. template <typename T, typename... Args>
  63. class Register {
  64. public:
  65.     explicit Register(const std::string& name)
  66.     {
  67.         Factory<Args...>::get().template reg<T>(name);
  68.     }
  69. };

  70. struct A : public Base {
  71.     inline static const Register<A, int> r1{"a"};
  72.     inline static const Register<A, int, const std::string&> r2{"a"};
  73.     inline static const Register<A, int, std::string&> r3{"a"};
  74.     inline static const Register<A, int, std::string> r4{"a"};
  75.     inline static const Register<A, int, const char*&> r5{"a"};

  76.     explicit A(int a)
  77.     {
  78.         std::cout << "Creating A(" << a << ")\n";
  79.     }

  80.     A(int a, const std::string& s)
  81.     {
  82.         std::cout << "Creating A(" << a << ", " << s << ")\n";
  83.     }
  84. };

  85. struct B : public Base {
  86.     inline static const Register<B> r{"b"};
  87.     // inline static Register<B> r2{"b"}; // abort at compile time
  88.     B()
  89.     {
  90.         std::cout << "Creating B()\n";
  91.     }
  92. };

  93. TEST(Factory, Simple)
  94. {
  95.     ASSERT_TRUE(create("a", 1));
  96.     ASSERT_TRUE(create("b"));
  97. }

  98. TEST(Factory, String)
  99. {
  100.     ASSERT_TRUE(create("a", 2, "hi"s));  // Args = {int, std::string}
  101. }

  102. TEST(Factory, StringLvalue)
  103. {
  104.     std::string s = "hi";
  105.     ASSERT_TRUE(create("a", 3, s));  // Args = {int, std::string&}
  106. }

  107. TEST(Factory, ConstStringLvalue)
  108. {
  109.     const std::string s = "hi";
  110.     ASSERT_TRUE(create("a", 4, s));  // Args = {int, const std::string&}
  111. }

  112. TEST(Factory, ConstCharPtr)
  113. {
  114.     const char* s = "hi";
  115.     ASSERT_TRUE(create("a", 5, s));  // Args = {int, const char*&}
  116. }

  117. TEST(Factory, CharArray)
  118. {
  119.     // Cannot find std::unique_ptr<Base> Factory<Args>::create(const string&, Args&& ...)
  120.     // [with Args = {int, const char (&)[3]}]
  121.     ASSERT_THROW(create("a", 6, "hi"), std::invalid_argument);  // runtime error

  122.     ASSERT_TRUE((create<int, std::string>("a", 7, "hi")));
  123. }

  124. TEST(Factory, InvalidParams)
  125. {
  126.     ASSERT_THROW(create("b", 1), std::invalid_argument);  // runtime error
  127. }

  128. int main(int argc, char** argv)
  129. {
  130.     ::testing::InitGoogleTest(&argc, argv);
  131.     return RUN_ALL_TESTS();
  132. }
复制代码


回复

使用道具 举报

🔗
cai_lw 2019-6-16 08:13:22 | 只看该作者
全局:
你这个需求是违背工厂模式的初衷的。如果不同的子类需要不同的初始化参数,那就用另一个函数来初始化,不要在构造函数里
回复

使用道具 举报

🔗
杨超越 2019-6-16 09:35:45 | 只看该作者
全局:
所以我写Java了....
回复

使用道具 举报

🔗
 楼主| 已注销-2317 2019-6-16 10:41:33 | 只看该作者
全局:
cai_lw 发表于 2019-6-16 08:13
你这个需求是违背工厂模式的初衷的。如果不同的子类需要不同的初始化参数,那就用另一个函数来初始化,不要 ...

工厂模式的初衷是什么,为什么这么做就违反了工厂模式的初衷了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表