#include <iostream>
#include <map>
std::map<const std::string, int> mTemp;
// C++11中std::pair模板函数原型是
// template< class T1, class T2 >
// std::pair<V1, V2> make_pair( T1&& t, T2&& u );
// 其中形参类型T1&&和T2&&是universal reference
// 当进行模板参数类型推导时,universal reference推导规则比较特殊:
// 当传入实参数是左值时,形参类型和模板参数都是左值引用类型
// 否则的话,形参类型是右值引用
void Fnc(const std::string& str, int n)
{
// 这里str和n都是左值(即可以取地址)
// 因此编译器从下面表达式自动推导出:
// 形参类型T1&& -> const std::string&
// 形参类型T2&& -> int&
// 模板参数类型T1 -> const std::string&
// 模板参数类型T2 -> int&
// 即std::make_pair函数类型是
// std::make_pair<const std::string&, int&>(const std::string&, int&)
mTemp.insert(std::make_pair(str, n));
// 而下面表达式中,模板参数类型已经给定,因此编译不会自动推导
// std::make_pair函数原型变成
// std::make_pair<const std::string, int>(const std::string&&, int&&)
// 注意此时形参类型是右值引用&&
// 而str和n都是左值,右值引用不能直接绑定左值,因此编译器报错。
// 其实可以通过std::move()把左值转换为右值引用,比如下面这样就不会报错了
// mTemp.insert(std::make_pair<const std::string, int>(std::move(str), std::move(n)));
mTemp.insert(std::make_pair<const std::string, int>(str, n)); //报错
// 这里std::make_pair的函数原型同上
// str.c_str()返回结果和2都是右值
// 实际调用的是
// mTemp.insert(std::make_pair<const std::string, int>(std::string(str.c_str()), 2))
mTemp.insert(std::make_pair<const std::string, int>(str.c_str(), 2)); //使用常量就不报错
}
int main()
{
std::string strTemp = "cc";
Fnc(strTemp, 2);
return 0;
}