导读

最近一直在研究 variant 相关内容,包括 variadic class,std::variant,std::any 等等。目的就是为了实现一个变体类型类。深入研究之后就会发现标准库实现为 std::variant 和 std::any 来面对两种场景是非常科学的。

我们之前也有提到,限于 C++17 的表现力和设计哲学,C++ 是无法真正实现动态的类型改变同时还能利用到其元编程等编译期的有力武器的,当然原话非是如此,但这就是我的理解的实际表达。

由于这个原因,我们看到两个类各有各的限制。std::variant 不能自适应全部 T,而是需要你事先给予一个类型表,而它不能接受运行期的类型改变。std::any 仿佛如 union 一般的内部实现,所以接受了运行期的类型改变,但却不能支持全面的类型抽取,而是需要你提供明确类型的抽取工具才行。

所以,上一篇文章关于 std::any 的抽取器方面的研究固然没有什么大的问题,但却都不是完满的解决。而事实上的确不可能为其构造一个一劳永逸的完满解决,否则,那就不是 C++,而是 ruby 或者 gradle 了。

我们曾经提到,经过预研,我们初步掌握了 C++17 当中的新的变体类型类,也确定了它们并不能完满地适合 cmdr-cxx 的需要。但 cmdr-cxx 的需要是什么呢?

实际上在 cmdr-cxx 的构思里,一个配置中心是可以有几种可行的方案的。如果你早已了解过 cmdr,就会知道 cmdr 不但提供命令行参数的 POSIX 兼容方式的界面解释,也提供一个全功能的内存中管理的 Option Store,它是一个树结构的配置中心。这个内存中的配置参数管理器不但和磁盘上的配置文件相互挂钩,也允许你将其和远程的配置服务中心相对接:在 Option Store 的 entry 被 set 时,你可以 hook 到事件并且提供一个写入远程配置中心的代码,而在应用程序初始化时,cmdr 提供了最恰当的装载远程配置中心数据的时机并允许你 hook 到这个点。

所以,出于工程需要的实际需求,在这样的大框架下,一个 entry 是可能动态改变数据类型的,很常见的可能的场景是这样的:

一个 entry,例如 host,原本支持一个 string 值,但下一迭代中它被改为了 string array。

其它的场景很多,例如原本是 int 类型,后来改为 bool。原来是 bool,后来改为 enum int 了。

实际上工程中这样的情况再常见不过。但我们并不一定非要因此而强求支持动态数据类型自适应性——没有什么事是重启不能解决的,如果不行,那就全部实例重启就是了。:P。别看这听起来很不负责任,可是哪怕是银行,不也时不时地通知说三天后午夜系统升级要暂停服务一晚上吗。你以为有几个人会真的有机会面对不能停的服务群去做架构决定?

所以在深入了解了现在的 C++ 的限制之后,cmdr-cxx 需要在支持度这里进行一个选择。是否应该支持运行期的类型可变呢?

像 cmdr 的 Golang 版本,其实都并没有支持运行期可变,为什么在 cmdr-cxx 我就飞了呢?还不是那些个 C++ 新特性勾引的,结果哪知道它们中看不中用,又或者说我从未在这个方面针对编译期和运行期有这样的深入的思考,才会以为说不定可以而投入精力。

人就是这样,一个念头起来了,就很难真的将其放下了。

所以只能是考虑不完满的版本也实现一份了。

很长时间以来,我一直没有考虑过在 C/C++ 这边做类库开源,一个原因在于 C++ 这二十年来作废了太多东西,我已经没法将过时的东西拿出来现了,那太需要勇气了,哪怕是没人知道我其实是一只会说话会写代码的狗。

另一个原因,自然是因为 C++ 这边的新式语法,编译器对其的支持一直没有正常过,今天来说 C++11 是很稳定地获得支持了,然而 17,2a 的形势就有点不知道该怎么论了,gcc 当然能支持,却有点笨重,而且无法减负,它原本是我们做事的首选的,clang 成为了事实上的桥头堡,但这家伙始终给人一种实验性的感觉,有点让人放不开,vc 以前曾经是我的主力挣钱工具,即使那时候它根本对标准不屑一顾,所以今天它对 C++ 标准很够支持了,却让人在反差中跳不出来。更重要的是,现在的 C++ 编译器往往都是庞大的,VC 那边,Visual Studio 怎么能只安装 C++ 部分呢,MFC 和 QT 都要用啊,C# 难道不香吗,为什么不顺便支持 Android 和 iPhone 呢,对的,这样做下来一整套安装的后果是什么你知道不知道?是超过 50GB 甚至可以达到 200GB 的磁盘占用,如果你还想顺便搞一点 Windows 驱动,或者 Linux 驱动等较低级的东西,那么再来几十 GB 吧,如果要经常性地做 Android 低级方面,Linux 低级方面的工作,你需要再来几百 GB 的空间为了虚拟机、核心编译工具链以及编译的中间结果以及最终结果。

系统发展成这样,实在是一种很怪异的事情。

因为它们仍然不具备足够的智能,更不必提智慧了。今天的全部 AI 线路上的一切内容,造就了那么庞大的盘子和生态,但它们事实上是毫无智慧的,评价它们的智力程度,它们连零岁都无法超越,因为这些都是模仿的智力,没有自我求解的智慧级能力。

强 AI 在可见的未来都是不可能实现的。虽然,实现了之后的后果或许人类根本无法承受。

但未来,永远不可琢磨,就好像爱因斯坦在他的年代从未想象过计算机所带来的世界的变革一样。真是希望他能够在现在的时代做出更不得了的创造。

哎,扯得太远,我是在说,C++ 变化太多,让人不想为其上做库。你做个库,本来很酷,结果过两天一 review,MD 你的代码又开始充斥着落后的 smells 了你觉得心情舒畅吗?尽管有时候人是应该不停止学习,但可能也不能这样,注定要废弃的东西我学来干嘛呢?

:end:

var_tstreamable_any 的完整代码有待于下一阶段完成之后在一并放出,敬请期待 cmdr-cxx,它将是 cmdr 命令行参数解释器的 cxx17 版本。

草草成篇——一个记录。以后有暇时再来 review 是否需要订正。