C++ 如何使_对知道其参数的类型?

C++ 如何使_对知道其参数的类型?,c++,stdmap,std-pair,C++,Stdmap,Std Pair,MSVC++“实用工具”标题中make_对的定义为: 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)); } 模板内联 配对配对(配对1、配对2、配对2) {/

MSVC++“实用工具”标题中make_对的定义为:

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)); } 模板内联 配对配对(配对1、配对2、配对2) {//由参数组成的返回对 返回(成对(_Val1,_Val2)); } 我一直使用make_pair,但没有将参数类型放在尖括号中:

map<string,int> theMap ; theMap.insert( make_pair( "string", 5 ) ) ; 地图主题图; 插入地图(配对(“字符串”,5)); 我是否应该告诉
make_pair
第一个参数是
std::string
,而不是
char*


它是如何知道的?

函数模板调用通常可以通过C++03§14.8.2中定义的参数推断来避免显式模板参数(即
make_pair
)。摘录:

当一个函数模板 专门化被引用,所有的 模板参数必须具有 价值观这些值可以是 明确指定的,或在某些情况下 案例,从使用中推断

具体的规则有点复杂,但通常只要您只有一个通常足够合格的专门化,它就“起作用”

您的示例使用了两个推导步骤和一个隐式转换步骤

  • make_pair
    返回一个
  • 然后,
    template pair::pair(pair const&)
    使用
    U=char*,V=int
    启动并执行成员初始化
  • 调用
    string::string(char*)
make_pair()
正好存在,因此可以使用参数类型推断来确定模板参数类型


请看这个SO问题:

它依赖于std::string的构造函数接受常量char*这一事实。 std::string的构造函数是否显式并不重要。模板推断类型,并使用pair的复制构造函数对其进行转换。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*)’
/usr/include/c++/4.3/bits/stl_pair.h:在构造函数“std::pair::pair(const std::pair&)[带_U1=const char*,_U2=int,_T1=const string,_T2=int]:
foo.cpp:27:从此处实例化
/usr/include/c++/4.3/bits/stl_pair.h:106:错误:从“const char*const”到“char*”的转换无效
/usr/include/c++/4.3/bits/stl_pair.h:106:错误:初始化“string::string(char*)”的参数1
构造函数如下所示:

  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) { }
模板
对(常数对和常数对)
:第一(u p.first),
第二(p.second){}
复制构造函数如下所示:

  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) { }
模板
对(常数对和常数对)
:第一(u p.first),
第二(p.second){}

它没有。生成一对(或者可能是一对)

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


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

模板
配对(配对和其他)
:第一(其他。第一)、第二(其他。第二)
{}

这可能以稍微不同的方式实现,但实际上是一样的。由于此构造函数是隐式的,编译器会尝试从您的pair中创建pair-因为必要的类型是可转换的,所以这可以工作。

+0 pair的构造函数是否是隐式的并不重要。我把它显式化了,它仍然可以工作;没有发生隐式转换。@eddy-仅仅因为您将其显式化并且代码“工作”并不意味着发生的事情就是您认为发生的事情。尝试创建自己的类类型对,只使用初始构造函数和类类型对的显式转换副本构造函数。除非你的编译器坏了,否则你会发现“显式”会使代码失败@GMan-我说的是pair的构造函数,而不是初始化列表中std::string的构造调用。@eddie-为了扩展,explicit关键字的全部目的是通过调用一个函数来禁止不希望的类型转换,该函数期望类型X的类型为Y,X可以从Y构造。换句话说,这意味着不允许讨论的代码类型。因此,如果您真的在std::pair中显式地创建了该构造函数,并且调用仍然有效,那么会发生一些事情,而不是您认为正在发生的事情。@noah-我确实按照您的建议创建了自己的构造函数对,并显式地创建了该构造函数。它不依赖于隐式转换。请参阅@potatohead的答案。第一部分是误导性的,但第二部分是正确的:您不告诉
make\u pair
类型,pair中的模板构造函数负责类型转换。@David:您能更具体地说明什么是误导性的吗?有两个推导步骤,其中一个是
make_pair
计算出自己的返回类型。“这是模板参数推导的完美示例”。。。问题是
make_pair
如何推断第一个元素是
字符串
,答案是它不是,而不是它是一个“完美的例子”。这涉及两个步骤,第二个步骤是执行转换的步骤。由于问题的后半部分准确无误,我投了赞成票。(这个词可能有误导性,它本身也有误导性:)。从技术上讲,标准规定类
X
的复制构造函数采用
X&
X const&
类型的单个参数。模板化构造函数永远不能是副本构造函数。(也就是说,如果类
X
定义了
模板X(T&);
,即使
X(f();
带有
f
返回的
X
与模板化的协构造函数匹配,编译器也将使用隐式生成的复制构造函数,而不是显式定义的模板化构造函数。)