vmp*_*str 78 c++ templates g++ rvalue-reference c++11
我正在使用启用了-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;
}
Run Code Online (Sandbox Code Playgroud)
我知道make_pair 意味着用作(1)情况(如果我指定类型,那么我也可以使用(3)),但我不明白为什么它在这种情况下失败了.
确切的错误是:
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 {aka std :: basic_string}')来键入'的std :: basic_string的&&'
同样,这里的问题只是"发生了什么?" 我知道我可以通过删除模板规范来解决问题,但我只是想知道这里的失败是什么.提前致谢.
编辑:
Jam*_*lis 124
这不是std::make_pair打算如何使用; 你不应该明确指定模板参数.
C++ 11 std::make_pair有两个参数,类型T&&和U&&,where T和U是模板类型参数.实际上,它看起来像这样(忽略返回类型):
template <typename T, typename U>
[return type] make_pair(T&& argT, U&& argU);
Run Code Online (Sandbox Code Playgroud)
当您调用std::make_pair并显式指定模板类型参数时,不会发生参数推断.相反,类型参数直接替换为模板声明,产生:
[return type] make_pair(std::string&& argT, int&& argU);
Run Code Online (Sandbox Code Playgroud)
请注意,这两个参数类型都是右值引用.因此,它们只能绑定到右值.对于您传递的第二个参数,这不是问题7,因为这是一个右值表达式. s但是,它是一个左值表达式(它不是临时的,它不会被移动).这意味着函数模板与您的参数不匹配,这就是您收到错误的原因.
所以,当你没有明确规定什么,为什么它的工作原理T,并U在模板参数列表?简而言之,右值参考参数在模板中是特殊的.部分由于称为引用折叠的语言特征,类型的右值引用参数(A&&其中A是模板类型参数)可以绑定到任何类型A.
不要紧,是否A是一个左,一个右值,const限定,挥发性合格,不合格或者,一个A&&可以绑定到该对象(同样,当且仅当A本身是一个模板参数).
在您的示例中,我们进行调用:
make_pair(s, 7)
Run Code Online (Sandbox Code Playgroud)
在这里,s是一个类型的左值std::string和7类型是右值int.由于您没有为函数模板指定模板参数,因此执行模板参数推导以确定参数是什么.
要绑定s一个左值,T&&编译器推断T为std::string&,产生一个类型的参数std::string& &&.但是,没有引用引用,所以这个"双引用"崩溃成为std::string&. s是一场比赛.
它的简单结合7到U&&:编译器可以推断U为int,产生类型的参数int&&,它成功地结合7,因为它是一个rvalue.
这些新语言功能有很多微妙之处,但如果你遵循一个简单的规则,那就很简单了:
如果可以从函数参数中推导出模板参数,那么可以推导出它.除非绝对必须,否则不要明确提供参数.
让编译器付出艰苦的努力,99.9%的时间它完全是你想要的.如果它不是你想要的,你通常会得到一个易于识别和修复的编译错误.
| 归档时间: |
|
| 查看次数: |
24300 次 |
| 最近记录: |