make_pair 如何知道其参数的类型?

发布于 2024-08-29 10:41:04 字数 507 浏览 5 评论 0原文

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*

它是怎么知道的?

The definition for make_pair in the MSVC++ "utility" header is:

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));
 }

I use make_pair all the time though without putting the argument types in angle brackets:

    map<string,int> theMap ;

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

Shouldn't I have to tell make_pair that the first argument is std::string and not char* ?

How does it know?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

看轻我的陪伴 2024-09-05 10:41:04

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

当函数模板
专业化被引用,所有
模板参数必须具有
价值观。这些值可以是
明确指定或在某些
案例,从使用中推断出来。

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

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

  • make_pair 返回一个 pair
  • 然后 templatepair::pair(pair const & ) 使用 U = char*, V = int 启动并执行成员初始化,
  • 调用字符串::字符串(char*)

Function template calls can usually avoid explicit template arguments (ie make_pair<…>) by argument deduction, which is defined by C++03 §14.8.2. Excerpt:

When a function template
specialization is referenced, all of
the template arguments must have
values. The values can be either
explicitly specified or, in some
cases, deduced from the use.

The specific rules are a bit complicated, but typically it "just works" as long as you have only one specialization which is generally qualified enough.

Your example uses two steps of deduction and one implicit conversion.

  • make_pair returns a pair<char const*, int>,
  • then template<class U, classV> pair<string,int>::pair( pair<U,V> const & ) kicks in with U = char*, V = int and performs member-wise initialization,
  • invoking string::string(char*).
乖乖公主 2024-09-05 10:41:04

事实并非如此。 make_pair 生成一对; (或者可能是一对)。

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


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

这可能以稍微不同的方式实现,但实际上是相同的。由于此构造函数是隐式的,因此编译器会尝试创建对;从你的配对中; - 由于必要的类型是可转换的,所以这是可行的。

It doesn't. make_pair generated a pair<char*,int> (or maybe a pair<char const*,int>).

However, if you'll note in the implementation of pair there's a templated copy constructor:


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

This may be implemented in slightly different ways but amounts to the same thing. Since this constructor is implicit, the compiler attempts to create pair<std::string,int> out of your pair<char*,int> - since the necessary types are convertible this works.

小傻瓜 2024-09-05 10:41:04

make_pair() 的存在正是为了可以使用参数类型推导来确定模板参数类型。

请参阅这个问题:使用自由函数作为伪函数-利用模板参数推导的构造函数

make_pair() exists precisely so that argument type deduction can be used to determine the template parameter types.

See this SO question: Using free function as pseudo-constructors to exploit template parameter deduction

梦在深巷 2024-09-05 10:41:04

它依赖于 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) { }

It relies on the fact that the constructor of std::string accepts a const char*.
It doesn't matter if this constructor of std::string is explicit or not. The template deducts the type and uses the copy constructor of pair to convert it. It also doesn't matter whether or not the pair constructor is explicit.

If you turn the constructor of std::string into:

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

you get this error:

/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*)’

The constructor looks like this:

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

The copy constructor looks like this:

template<class _U1, class _U2>
pair(const pair<_U1, _U2>& __p)
    : first(__p.first),
      second(__p.second) { }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文