C++的模板其实是个挺纠结的东西,用的不好的话,编译的一堆错误够你调到崩溃,但要是用的好呢,又确实非常方便,我们来看看

一.获取数组长度
比如

怎么获取 arr 的长度呢?
最简单的代码:

但是这样也带来一个问题,万一是个新手程序员:

就有问题了……
那么有没有办法,有一种安全的方法,当发现传入的是指针的时候,自动编译报错呢?
有的,模板里面可以推导出数组的长度。
所以我们可以使用如下代码

这样,当传入指针的时候,编译就会报错了。
而同时你肯定也能看出,我们甚至能指定只能传入数组长度为固定某数字的数组了,怎么做我就不用讲了吧?

二.切片函数
python中的切片函数真是令人怀念,并且即使传入的参数超过长度也不会崩溃,可是C++里面则就会出现问题,所以通常我们要把一个容器的数据做切片时,代码如下:

注: 如果直接如下调用,会导致取到end()之后多余的数据

其实这代码还是挺纠结,而且并不通用(各种类型的容器都要重复写代码),所以我们也可以用模板来优化一下,代码如下:

可以注意到代码中使用了typeof,这也是C++挺好用的一个特性。
所以无论是什么类型的容器,只要如下调用即可

三.获取类名
当在使用模板,或者使用继承关系的类时,我们经常需要在打印Log时清楚的知道到底是哪个类的实例在执行。
所以我们可以用这个函数:

如果实在类实例内部:

OK,需要介绍的内容就是这样了~~

说句后话,python的确要比C++方便很多,但是在C++中经常会有这样的情景:在经过长时间尝试之后,“哇,原来这样能实现!”其实也是很不错的过程~比如之前的另一个宏定义:

vimer.cn原创vim(gvim)插件load_template正式发布

最近准备已久的模板载入插件 load_template 终于搞定了,现在正式放出下载大家使用.www.vim.org上已经放出了下载链接,如下: http://www.vim.org/scripts/sc...

阅读全文

关于map,vector中数据类型使用模板的问题

众所周知,大名鼎鼎的STL使用大量的模板,但是有时候我们也会面临一些需求,比如map或者vector里的数据类型被定义成模板,但这个时候,用起来就会出现问题。 ...

阅读全文

38则回应给“C++模板的几个应用”

  1. cndj说道:

    typeof是编译器提供的吗? 好似没在标准里面看过, 不过用0x的auto应该也能实现相同的功能

    [回复]

    Dante 回复:

    GCC家族里有,MS那套很久没用了,不太清楚。。

    [回复]

  2. fanhe说道:

    typeof 貌似不是 c++ 的东西吧? 只知道有 typeid.
    c++ 是有很多技巧, 也相当复杂…

    [回复]

    Dante 回复:

    不知道gcc家族里特有的还是ms也有。。不过还是挺方便的。

    [回复]

  3. Huang Yun说道:

    typeof 似乎不是标准,在C++11里面有auto和decltype

    [回复]

  4. 打工战士说道:

    而同时你肯定也能看出,我们甚至能指定只能传入数组长度为固定某数字的数组了,怎么做我就不用讲了吧?
    不明白……求教

    [回复]

    Dante 回复:

    T (&array)[N]

    这里的N写为固定的值就可以啦~

    [回复]

    打工战士 回复:

    谢谢!
    刚刚用gdb看了一下,数组名作为参数传进arraysize的时候,那个参数N就被初始化成数组的大小了。那么固定数组也是一样的道理了。
    只是还有一个地方不太明白,参数N是怎么被初始化成数组size的呢?

    [回复]

    Dante 回复:

    这是C++的模板推导~

    [回复]

  5. oldman说道:

    for_each 迭代那个例子可以使用 c++11中的auto 来推演类型(vs2010与gcc现在都已经支持)

    不过既然都c++11了,那就干脆就用新版的for语法了(说新,其实其他语言都已经这么干了)(vs2010不支持,2012没试过-xp装不上。。)

    或者你如果足够蛋疼可以试试Boost.Foreach

    [回复]

  6. yafei.zhang@langtaojin.com说道:

    Cut2Part这个函数不是C++的风格

    应该接受迭代器为参数的

    [回复]

  7. yafei.zhang@langtaojin.com说道:

    typeof也只是GCC的扩展.
    你最后一个例子为什么不去看看BOOST_FOREACH是如何实现的.

    腾讯的不合格C++工程师真多

    [回复]

    Dante 回复:

    只针对你最后一句话。
    我实在不理解,你是否一定要用这种说话方式来找自信呢?

    [回复]

    yafei.zhang@langtaojin.com 回复:

    我呆过, 知道情况, 一把一把的不合格的

    [回复]

    Dante 回复:

    第一,我无法理解你所谓的合不合格的标准
    第二,我不知道你有没有判断别人是否合格的资格
    第三,就做人来说,我觉得你沟通的方式有些问题

    本博不想有这些无谓的争吵,有一争高下之心,大可绕道。

    [回复]

    yafei.zhang@langtaojin.com 回复:

    就事论事, 没必要吵.

    那你觉得你这篇文章里的哪一个piece写的比较精彩呢?

    [回复]

    yafei.zhang@langtaojin.com 回复:

    如果我的语言打击到你, 我表示道歉.

    我只是觉得有更优雅通用的方式, 没必要像你这样写的这么憋屈.

    [回复]

    Dante 回复:

    呵呵,本来我就不认同,怎么会受打击。

    同样,优雅通用与否,憋屈与否也是见仁见智。
    所以,你发表你的看法我没有意见,但是带有人身攻击的词语,这里不欢迎。

    [回复]

    yafei.zhang@langtaojin.com 回复:

    说了点事实就成攻击了. 来点真东西.

    我提几个具体的意见给你的Cut2Part函数,免得一些纸上谈兵.你自己看看是不是更优雅通用了:

    1.uint32_t不是C++标准中的,是C99中中的内容, 如果拿不准, uint32_t可以作为第三个模板参数,交给编译器去处理这个类型.
    2.函数返回值的意义? 如果没有意义, 那为什么还要返回?
    3.typeof也不是C++标准支持的, 是GCC扩展. 如果你不知道迭代器所指元素的类型, 可以用std::iterator_traits::value_type将其萃取出来, 但同时要求你所传入的参数不是一个容器, 而是一对迭代器.(即便传入容器, 也可以用typename P::iterator作为其迭代器)
    4.你的容器所支持的迭代器如果不是随机访问迭代器, src.begin() + index;这样的操作是编译不过的, 可以使用std::advance将迭代器前进. 同样, 迭代器的小于比较也不是都支持的.

    [回复]

    Zind 回复:

    这位朋友,我实在看不下去了……
    博主发文,是为了交流技术,分享心得……你在这里大放厥词,是为了砸场子么?
    我姑且承认你是大牛,态度也不至于这么嚣张吧?如果认为这里太弱智,大可绕道。

    [回复]

    Dante 回复:

    感谢zind的支持~
    yarfei,技术交流本身是件开心的事,何必这么浓的火药味。。

    [回复]

    yafei.zhang@langtaojin.com 回复:

    hi, 是你自己把火药味弄浓了, 我说的关于tx的事情都是我亲身体会. 我以前是在tx bj的. 不是专门针对你.

    [回复]

    Dante 回复:

    OK,那就休战吧。

    [回复]

    yafei.zhang@langtaojin.com 回复:

    取决于你的态度, 我一直都没有认为是战斗啊.

    [回复]

    yafei.zhang@langtaojin.com 回复:

    如果你对C++ STL了解充分, 完全还可以这样写, 比专门写一个函数简洁多了…

    哪种好, 你自己可以比较一下.

    #include
    #include
    #include
    #include

    int main()
    {
    std::vector src;
    std::list dst;
    size_t index = 0, count = 0;

    // …
    //Cut2Part(src, index, count, dst);
    //等价于
    if (src.size() > index + count)
    std::copy(src.begin()+index, src.end()+index+count, std::front_inserter(dst));
    return 0;
    }

    [回复]

    Dante 回复:

    yafei,没有人质疑你的能力,而是在说交流的态度,如果你只是想证明你更强,好吧,你赢了。

    [回复]

  8. Zind说道:

    我也来班门弄斧一个:
    // initialize elements of an array to 0
    template void init_array(T (&array) [N])
    {
    for (size_t i = 0; i != N; ++i)
    {
    array[i] = 0;
    }

    return ;
    }

    [回复]

    Zind 回复:

    呃……我不知道怎么发帖啊,那一对尖括号似乎是被转义掉了……
    template 里面应该是有 typename T, size_t N

    [回复]

    Dante 回复:

    可以用pre标签哈,这个页面最上面有介绍:
    http://www.vimer.cn/index.php/%E7%95%99%E8%A8%80

    [回复]

    Dante 回复:

    模板推导,我也很喜欢用,哈哈

    [回复]

    Zind 回复:

    博主别跟 ls 的某某一般见识。
    它既然知道你是哪家公司的,应该是关注你博客有些时间了,肯定也读过你的不少博文。无论它从你的博客中是否学到了东西,或者学到了多少,这样对待一个知识产出者,都是无法接受的。

    [回复]

    yafei.zhang@langtaojin.com 回复:

    是, 我是学习VIM的, 我是VIM菜鸟.
    互相取长补短, 他的C++水平是不好, 远远差于他的VIM水平啊.

    [回复]

  9. tecbbs说道:

    请教博主用的代码高亮插件是不是wp-syntax?
    我的wordpress3.3.1用wp-syntax有点问题,下面的文章
    http://zhixing.tecbbs.com/archives/2012/02/18/241

    我的将显示成了<和&gt:

    [回复]

    Dante 回复:

    很奇怪。。我有个朋友也说有这个问题,但是我自己用确实就没问题。。至今也不明白原因。。

    [回复]

    tecbbs 回复:

    我找到原因了,是我同时开了wp-syntaxhighlighter,关了就好了

    [回复]

  10. hehe说道:

    其实作为一个学习者,我最喜欢出现像yafei.zhang这样的大牛来对我炮轰,要知道敢炮轰别人的,那都是有两把刷子的,如果你一旦虚心向炮轰我们的大牛请教,你的知识和见识会瞬间爬上一个高境界,这是求之不得的机会,所以我觉得博主应该赶紧对这些大牛表示感激涕零啊。而不是用凡夫俗子的观念来指责大牛的态度,大牛人家的自信和高傲是建立在扎实的学习之上的,不信你去挑挑大牛的代码的刺,人家一定对你感激,就算你骂大牛傻逼但是给出更牛逼的解答,大牛没准会和你做朋友。
    就这个大牛对你的代码点评来说,你的C++代码确实写得像一坨屎。人家大牛的方案的确更为纯粹,这其实是高人指点你。所以如果真的是虚怀若谷的话,何必介意大牛的语气呢。

    [回复]

发表评论