# 看得到想不到的坑:std::make_pair与std::pair 今天捣鼓[[https://github.com/metorm/Rocstar|Rocstar]],编译的时候碰上了一个`C++11`的坑,属于那种不告诉你的话,给你代码你都看不出来异常的坑。出问题的那段代码长这样: int node_id1 = fne[j],node_id2 = fne[(j+1)%nj]; if(node_id1>node_id2) std::swap(node_id1, node_id2); e2f_it = e2f.find(std::make_pair(node_id1,node_id2)); if(e2f_it != e2f.end()){ afs.insert(std::make_pair(e2f_it->second,i)); e2f.erase(e2f_it); } else{ e2f.insert(std::make_pair,int>( std::make_pair(node_id1,node_id2) ,i)); } 上下文不怎么明确,但猜一猜也知道是怎么回事。看起来跟平时用的`std::pair`没啥区别吧?然而它就是报错了: `Cannot convert parameter 1 from 'int' to 'int &&'` 检查了半天,确定`node_id1`和`node_id2`兄弟俩确实是`int`,这怎么可能错?实在受不了的我还去看了这一段的STL源码: #if __cplusplus >= 201103L // NB: DR 706. template constexpr pair::__type, typename __decay_and_strip<_T2>::__type> make_pair(_T1&& __x, _T2&& __y) { typedef typename __decay_and_strip<_T1>::__type __ds_type1; typedef typename __decay_and_strip<_T2>::__type __ds_type2; typedef pair<__ds_type1, __ds_type2> __pair_type; return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y)); } #else template inline pair<_T1, _T2> make_pair(_T1 __x, _T2 __y) { return pair<_T1, _T2>(__x, __y); } #endif 显然,在`201103L`之后,标准有过一次变更。`Rocstar`估计就是那种万年`gcc-4.8`的工程,所以**估计**用旧版本编译器就过去了。但新版究竟是怎么错的?看上面的新版代码也不知所以然。没办法,放下面子搜错误吧,还真在[[https://stackoverflow.com/questions/19358240/weird-compiler-error-cannot-convert-parameter-from-int-to-int|这里]]找到了,问题出在新版`make_pair`的`__decay_and_strip<_T1>`这部分。 具体来说,就是`C++11`之后模板推导形式不一样了,合法的用法只有两种: num_text.push_back(std::make_pair(num, text)); // deduced type num_text.push_back(std::pair(num, text)); // specific type 作为一个从`C++11`时代才开始深入学习的人来说,只有看到这里明明白说出来,才能想起来平时写`std::make_pair`是不带尖括号的。 改起来就容易了,把原文中`make_pair`一类语句中的尖括号全删掉就好了。