make_pair如何知道其args的类型?

时间:2010-04-19 22:59:35

标签: c++ stdmap std-pair

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

template<class _Ty1,
 class _Ty2> inline
 pair<_Ty1, _Ty2> make_pair(_Ty1 _Val1, _Ty2 _Val2)
 { // return pair composed from arguments
 return (pair<_Ty1, _Ty2>(_Val1, _Val2));
 }

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

    map<string,int> theMap ;

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

我不应该告诉make_pair第一个参数是std::string而不是char*吗?

它是如何知道的?

4 个答案:

答案 0 :(得分:12)

函数模板调用通常可以通过参数推导避免显式模板参数(即make_pair<…>),参数推导由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*)

答案 1 :(得分:9)

没有。 make_pair生成了一对&lt; char *,int&gt; (或者可能是一对&lt; char const *,int&gt;)。

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


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

这可能会以稍微不同的方式实现,但却相同。由于此构造函数是隐式的,因此编译器会尝试创建pair&lt; std :: string,int&gt;你的一对&lt; char *,int&gt; - 由于必要的类型是可转换的,这是有效的。

答案 2 :(得分:1)

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

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

答案 3 :(得分: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) { }