3

MSVC++“实用程序”标头中 make_pair 的定义是:

模板<class _Ty1,
 类 _Ty2> 内联
 对<_Ty1, _Ty2> make_pair(_Ty1 _Val1, _Ty2 _Val2)
 { // 由参数组成的返回对
 返回(对<_Ty1,_Ty2>(_Val1,_Val2));
 }

尽管没有将参数类型放在尖括号中,但我一直使用 make_pair:

    map<string,int> theMap ;

    theMap.insert(make_pair("string", 5));

我不应该说make_pair第一个论点是std::string而不是char*吗?

它是怎么知道的?

4

4 回答 4

12

函数模板调用通常可以make_pair<…&gt;通过参数推导避免显式模板参数(即),这是由 C++03 §14.8.2 定义的。摘抄:

引用函数模板特化时,所有模板参数都必须有值。这些值既可以明确指定,也可以在某些情况下从使用中推导出来。

具体规则有点复杂,但通常只要您只有一个通常足够合格的专业,它“就可以工作”。

您的示例使用了两步演绎和一个隐式转换。

  • make_pair返回一个pair<char const*, int>
  • 然后template<class U, classV> pair<string,int>::pair( pair<U,V> const & )启动U = char*, V = int并执行成员初始化,
  • 调用string::string(char*).
于 2010-04-19T23:03:31.827 回答
9

它没有。make_pair 生成了一对<char*,int>(或者可能是一对<char const*,int>)。

但是,如果您在 pair 的实现中注意到有一个模板化的复制构造函数:


template < typename Other1, typename Other2 > 
pair(pair<Other1,Other2>& other) 
  : first(other.first), second(other.second)
{}

这可能以稍微不同的方式实现,但相当于同一件事。由于此构造函数是隐式的,因此编译器会尝试从您的 pair<char*,int> 中创建 pair<std::string,int> - 因为必要的类型是可转换的,这是可行的。

于 2010-04-19T23:06:16.097 回答
1

make_pair()精确存在,因此可以使用参数类型推导来确定模板参数类型。

请参阅这个 SO 问题:Using free function as pseudo-constructors to exploit template parameter deduction

于 2010-04-19T23:03:42.307 回答
1

它依赖于 std::string 的构造函数接受 const char* 的事实。std::string 的这个构造函数是否显式都没关系。模板扣除类型,使用pair的拷贝构造函数进行转换。对构造函数是否显式也无关紧要。

如果你把 std::string 的构造函数变成:

class string
{
public:
    string(char* s)
    {
    }   
};

你得到这个错误:

/usr/include/c++/4.3/bits/stl_pair.h: In constructor ‘std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 = const char*, _U2 = int, _T1 = const string, _T2 = int]’:
foo.cpp:27:   instantiated from here
/usr/include/c++/4.3/bits/stl_pair.h:106: error: invalid conversion from ‘const char* const’ to ‘char*’
/usr/include/c++/4.3/bits/stl_pair.h:106: error:   initializing argument 1 of ‘string::string(char*)’

构造函数如下所示:

  template<class _U1, class _U2>
    pair(const pair<_U1, _U2>& __p)
    : first(__p.first),
      second(__p.second) { }

复制构造函数如下所示:

template<class _U1, class _U2>
pair(const pair<_U1, _U2>& __p)
    : first(__p.first),
      second(__p.second) { }
于 2010-04-19T23:04:23.607 回答