模板元编程从本质上看和函数编程有些类似。其实偏底层的语言就是有这个好处,怎么抽象怎么封包一下,就会和高级的语言或者其它应用方式感觉相同。c++的元编程,对每一个c++开发人员来说,都是一个很深的技术,会用和会写到会设计,这需要一个很长的时间才能达到。更不要提到最后融会贯通,自由收发。
模板元编程,其实在底层库或者框架中应用更多,这也是为什么很多c++开发人员为什么写了很多代码,工作了很长时间也没有没接触过的原因。毕竟,咱们国内的整体软件形式大家也都明白,拿来主义还是盛行。这里不谈此风好与坏,合适的就是最好的。
早期的元编程在知乎上有人挖过坟,是一个不能编译成功的例子,后来慢慢被一些牛人完善出来。它是一种不经意的过程,是一种模板编程的外溢。这种提法其实就是说明,它的编程模式和普通的模板编程模式是有区别的,这种区别就是不让一般开发者容易明白。包括在后来看到的SFINAE技术。当真,对大多数人来说,这不是技法,更像灾难。飞机很好用,但不会开。
c++的标准委员会当然不会坐视不理,毕竟,牛人自己写那个也麻烦啊,就像开飞机,不小心,飞机就要掉来来的感觉。所以基础设施不断的随着标准的升高而完善,从一些新的模板类和函数封装起来,减少复杂度增加易接受程度到干脆另起炉灶引入更新的概念和更好的基础设施。Concepts就是一个典型的例子。
不可否认,相对于其它语言,c++语言本身的应用就是复杂的(灵活)。而模板编程则更上一层,正如有的人在网上所言,他们公司禁止使用模板。模板编程的难点对于初学者是非常不友好的,一个重要的体现点在于,模板的错误,即使非常小,也会有一大片的错误,可能大多数人一下子就晕了。那么可想而之,高手们眼中模板元编程是一门新语言的建议,能不让新手们望而却步么?更何况,它的应用范围又不大(虽然很底层,是一个重要的基础设施)。
这样看来,这不是c++标准委员会的大牛们想看的。毕竟,用得多,用得广,才会使c++更容易不断发展下去。那么在新的c++11及以上标准里就提供了大量的简化的元编程方法,大量的元函数被封装起来,直接被调用,更是在c++20推出了Concepts进一步简化相关的元编程的应用。
下面看几个提供的常用的元函数:
std::is_integral:整形检查
std::is_same:二者类型是否一致
std::integral_constant:包装特定数据类型,在bool时可用于元编程的分支控制
std::enable_if:根据第一个形参的bool值得确定第二个形参的公开成员typedef type是否使用
std::integer_sequence:这个在前面用过,元编程中产生整数序列(数组)
更多的请参考:https://en.cppreference.com/w/cpp/meta#Type_traits
元编程确实难,但只要坚持用,坚持思考,达到在实际中应用还是没有什么问题的。
讲了很多元编程的优点,但在实际应用中其实还是有不少困难的。最典型的就是两个:
1、开发,首先是一个编程习惯和开发思想的转换,包括设计思想,代码调试手段等等,都需要转变。另外前面提到过,元编程主要在库和框架中使用,而这点在国内恰恰又是短板中的短板(国内更强调用功能),所以互相学习的可能性以及获取帮助的可能性都很小。这就意味着出现问题,更多的依赖自己去查找资料。
2、应用,一般来说,开发一个动态库甚至一个框架,只要给个头文件说明基本就搞定了,而相关的算法和需要控制的代码都被安全的放在库里。而元编程采用模板技术,代码的实现目前基本只能在头文件中,也就是说,交出头文件的同时,源码就全暴露了。而模板的特性是不使用不编译,所以如果当使用一个头文件时或者多处使用时,就会发现编译时间增加了(当然,小规模的应用就忽略了)。同时,还有一个更重要的问题,一般应用方的很少有对技术掌握特别深的,这就意味着,给对方元编程的代码文件,如果没有详细的说明文档,对方可能会很排斥,毕竟模板本身就很复杂了,再加个元编程。
这里给大家推荐几本书,正如在前面介绍,学好c++模板元编程,其实主要有三本书可以做为打基础(有的是有多个版本也算一个),一个是《C++ Templates The Complete Guide》,这个第一版中有侯捷老师版本的,有陈伟柱老师版本的,最新又出来了第二版,可惜没有比较正式的中文版。另外一个是《Modern c++Design》中文版叫《c++设计新思维》;还有一个就是《c++模板元编程》(c++ Template Metaprogramming),这些书相对来说都比较老了。有一本国内牛人写的书《c++模板元编程实战》值得学学。
其它还有很多书籍,大家在学习完成上面的书后可以参考。网上也有很多牛人的相关的博客或者公众号,大家取其精华即可。
学习是一个漫长的过程,不要妄想一蹴而就。
还以前面的函数判断为例子,就可以看出的版本前进引起的简化:
1、老版本
template <typename T, void (T::*)(const typename T::value_type&)>
struct IsHave;
template <typename T, void (T::*)(typename T::value_type)>
struct IsHas;
template <typename T>
bool ishas(...)
{
return false;
}
template <typename T>
bool ishas(IsHave<T, &T::push_front>*)
{
return true;
}
template <typename T>
bool ishas(IsHas<T, &T::push_front>*)
{
return true;
}
int main()
{
std::cout << ishas<std::list<int> >(NULL) << std::endl;
std::cout << ishas<std::vector<int> >(NULL) << std::endl;
return 0;
}
看上去还是有点复杂,但是它和前面的must判断原理是一样的,通过替换是否成功来决定结果。
2、c++11版本
c++11版本就简单不少,看下面的例子:
template <typename>
using void_t = void;
template <typename T, typename V = void>
struct IsHave :std::false_type {};
template <typename T>
struct IsHave<T, void_t<decltype(std::declval<T>().push_front(std::declval<typename T::value_type>()))>> :std::true_type {};
int main()
{
std::cout << IsHave<std::list<int>>::value << std::endl;
std::cout << IsHave<std::vector<int>>::value << std::endl;
return 0;
}
这个相对上面就更简单更容易理解,而且更灵活。
3、c++20更新版本
在concept推出后,这个版本更简化了,前面有太多的例子了,这里就不再重复,有兴趣可以根据前面的再结合此例子写一下。
模板元编程写到这里,暂时先告一个段落。基本的元编程的技术都覆盖到了,更深或者更抽象的设计这个需要不断的迭代理论和实践,不断的紧跟着c++标准前进。可能以前复杂的方式在高版本的c++标准里就是简单的一两行代码,但是这两行代码恰恰是前面复杂实现过程中不断总结抽象出来的经验。
不断自省,不断前进,不断挑战自我,与诸君共勉。
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。
运行bundleinstall后出现此错误:Gem::Package::FormatError:nometadatafoundin/Users/jeanosorio/.rvm/gems/ruby-1.9.3-p286/cache/libv8-3.11.8.13-x86_64-darwin-12.gemAnerroroccurredwhileinstallinglibv8(3.11.8.13),andBundlercannotcontinue.Makesurethat`geminstalllibv8-v'3.11.8.13'`succeedsbeforebundling.我试试gemin
网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识
我正在使用Mandrill的RubyAPIGem并使用以下简单的测试模板:testastic按照Heroku指南中的示例,我有以下Ruby代码:require'mandrill'm=Mandrill::API.newrendered=m.templates.render'test-template',[{:header=>'someheadertext',:main_section=>'Themaincontentblock',:footer=>'asdf'}]mail(:to=>"JaysonLane",:subject=>"TestEmail")do|format|format.h
所以这可能有点令人困惑,但请耐心等待。简而言之,我想遍历具有特定键值的所有属性,然后如果值不为空,则将它们插入到模板中。这是我的代码:属性:#===DefaultfileConfigurations#default['elasticsearch']['default']['ES_USER']=''default['elasticsearch']['default']['ES_GROUP']=''default['elasticsearch']['default']['ES_HEAP_SIZE']=''default['elasticsearch']['default']['MAX_OP
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or