我刚刚玩了启用-std = c 11的g 4.7(后面的一个快照) . 我试图编译一些现有的代码库,一个失败的案例让我感到困惑 .
如果有人能解释发生了什么,我将不胜感激 .
这是代码
#include <utility>
#include <iostream>
#include <vector>
#include <string>
int main ( )
{
std::string s = "abc";
// 1 ok
std::pair < std::string, int > a = std::make_pair ( s, 7 );
// 2 error on the next line
std::pair < std::string, int > b = std::make_pair < std::string, int > ( s, 7 );
// 3 ok
std::pair < std::string, int > d = std::pair < std::string, int > ( s, 7 );
return 0;
}
我知道make_pair意味着用作(1)情况(如果我指定类型,那么我也可以使用(3)),但是我在这种情况下没有失败't understand why it' .
确切的错误是:
test.cpp:在函数'int main()'中:test.cpp:11:83:错误:没有匹配函数来调用'make_pair(std :: string&,int)'test.cpp:11:83:注意:候选人是:在/gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c /4.7中包含的文件.0 / utility:72:0,来自test.cpp:1:/gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../ ../include/c /4.7.0/bits/stl_pair.h:274:5:注意:模板constexpr std :: pair :: __ type,typename std :: __ decay_and_strip <_T2> :: __ type> std :: make_pair( _T1 &&,_T2 &&)/gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c /4.7.0/bits /stl_pair.h:274:5:注意:模板参数推断/替换失败:test.cpp:11:83:注意:无法将's'(类型'std :: string ')转换为输入'std :: basic_string &&'
同样,这里的问题只是“发生了什么?”我知道我可以通过删除模板规范来解决问题,但我只是想知道这里的失败是什么 . 提前致谢 .
编辑:
-
g 4.4编译此代码没有问题 .
-
正在删除-std = c 11也可以编译代码而没有任何问题 .
1 回答
这不是如何使用
std::make_pair
;你不应该明确指定模板参数 .C 11
std::make_pair
有两个参数,类型为T&&
和U&&
,其中T
和U
是模板类型参数 . 实际上,它看起来像这样(忽略返回类型):当您调用
std::make_pair
并显式指定模板类型参数时,不会发生参数推断 . 相反,类型参数直接替换为模板声明,产生:请注意,这两个参数类型都是右值引用 . 因此,它们只能绑定到右值 . 对于传递的第二个参数
7
,这不是问题,因为这是一个右值表达式 . 但是,s
是一个左值表达式(它不是被移动的't a temporary and it isn') . 这意味着函数模板与您的参数不匹配,这就是您收到错误的原因 .那么,为什么当你没有明确指定模板参数列表中的
T
和U
时,它是否有效?简而言之,右值参考参数在模板中是特殊的 . 部分由于称为引用折叠的语言功能,A&&
类型的右值引用参数(其中A
是模板类型参数)可以绑定到任何类型的A
.无论
A
是左值,右值,const限定,volatile限定还是不合格都无关紧要,A&&
可以绑定到该对象(同样,当且仅当A
本身是模板参数时) .在您的示例中,我们进行调用:
这里,
s
是std::string
类型的左值,7
是int
类型的右值 . 由于您没有为函数模板指定模板参数,因此执行模板参数推导以确定参数是什么 .要将
s
(一个左值)绑定到T&&
,编译器会将T
推导为std::string&
,从而产生类型为std::string& &&
的参数 . 但是,没有对引用的引用,因此"double reference"折叠成std::string&
.s
是一场火柴 .将
7
绑定到U&&
很简单:编译器可以推导U
为int
,产生类型为int&&
的参数,该参数成功绑定到7
,因为它是一个右值 .这些新的语言功能有很多微妙之处,但是如果你遵循一个简单的规则,它就很容易: