关于std::make_pair()使用的问题

关于std::make_pair()使用的问题
代码如下
#include 
#include 

std::map<const std::string, int> mTemp;

void Fnc(const std::string& str, int n)
{
    mTemp.insert(std::make_pair(str, n));
    mTemp.insert(std::make_pair<const std::string, int>(str, n)); //报错
    mTemp.insert(std::make_pair<const std::string, int>(str.c_str(), 2)); //使用常量就不报错
}

int main()
{
    std::string strTemp = "cc";
    Fnc(strTemp, 2);
    
    return 0;
}

为什么在make_pair后添加了就只能使用常量?
#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;
}