今天捣鼓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<int,int>(node_id1,node_id2));
if(e2f_it != e2f.end()){
afs.insert(std::make_pair<int,int>(e2f_it->second,i));
e2f.erase(e2f_it);
}
else{
e2f.insert(std::make_pair<std::pair<int,int>,int>(
std::make_pair<int,int>(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<typename _T1, typename _T2>
constexpr pair<typename __decay_and_strip<_T1>::__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<typename _T1, typename _T2>
inline pair<_T1, _T2>
make_pair(_T1 __x, _T2 __y)
{ return pair<_T1, _T2>(__x, __y); }
#endif
显然,在201103L
之后,标准有过一次变更。Rocstar
估计就是那种万年gcc-4.8
的工程,所以估计用旧版本编译器就过去了。但新版究竟是怎么错的?看上面的新版代码也不知所以然。没办法,放下面子搜错误吧,还真在这里找到了,问题出在新版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<int, std::string>(num, text)); // specific type
作为一个从C++11
时代才开始深入学习的人来说,只有看到这里明明白说出来,才能想起来平时写std::make_pair
是不带尖括号的。
改起来就容易了,把原文中make_pair<int,int>
一类语句中的尖括号全删掉就好了。