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*
吗?
它是如何知道的?
答案 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) { }