C ++ 11 make_pair与指定的模板参数不编译 [英] C++11 make_pair with specified template parameters doesn't compile

查看:4104
本文介绍了C ++ 11 make_pair与指定的模板参数不编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是使用g ++ 4.7(稍后的快照之一)和-std = c ++ 11启用。我试图编译一些我现有的代码库和一个失败的情况有点困惑。



我会感激,如果有人可以解释发生了什么。

以下是代码

  #include< utility> 
#include< iostream>
#include< vector>
#include< string>

int main()
{
std :: string s =abc;

// 1 ok
std :: pair< std :: string,int> a = std :: make_pair(s,7);

//下一行的错误
std :: pair< std :: string,int> b = std :: make_pair< std :: string,int> (s,7);

// 3 ok
std :: pair< std :: string,int> d = std :: pair< std :: string,int> (s,7);

return 0;
}



我知道make_pair是作为(1)case(如果我指定的类型,那么我可以使用(3)),但我不明白为什么它在这种情况下失败。



确切的错误是:


test.cpp:在函数'int main()':
test.cpp: 11:83:错误:没有匹配的函数调用'make_pair(std :: string& int,')
test.cpp:11:83:note:candidate is:
在包括/ gcc4.7 / usr / local / lib / gcc / i686-pc-linux-gnu / 4.7.0 /../../../../include/c ++ / 4.7.0 / utility:72:0,
从test.cpp:1:
/gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../。 ./include/c++/4.7.0/bits/stl_pair.h:274:5:
note:template constexpr std :: pair :: __ type,typename
std :: __ decay_and_strip< _T2> :: __type> std :: make_pair(_T1&&&&&)
/gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../。 ./../../include/c++/4.7.0/bits/stl_pair.h:274:5:
note:模板参数扣除/替换失败:
test.cpp:11:83 :note:can not convert's'(type'std :: string {aka std :: basic_string}')to type'std :: basic_string&'


同样,这里的问题只是发生了什么?我知道我可以通过删除模板规范来解决这个问题,但我只是想知道这里的失败在底下。提前感谢。



编辑:




  • g ++ 4.4编译此代码



< h2_lin>解决方案

这不是如何使用 std :: make_pair 你不应该明确指定模板参数。



C ++ 11 std :: make_pair T&&& U&&& 类型的参数,其中 code>和 U 是模板类型参数。实际上,它看起来像这样(忽略返回类型):

  template< typename T,typename U> 
[return type] make_pair(T&&& argT,U&&& argU);

当您调用 std :: make_pair 显式指定模板类型参数,不会进行参数扣除。相反,类型参数直接替换为模板声明,产生:

  [return type] make_pair(std :: string& & argT,int&& argU); 

请注意,这两个参数类型都是右值引用。因此,它们只能与右值绑定。这不是你传递的第二个参数的问题, 7 ,因为这是一个右值表达式。 s ,但是,是一个左值表达式(它不是一个临时的,它不被移动)。这意味着函数模板不是你的参数的匹配,这就是为什么你得到错误。



所以,为什么它工作,当你没有明确指定什么 T U 是否在模板参数列表中?简而言之,右值引用参数在模板中是特殊的。部分由于称为参考折叠的语言特征, A&& 类型的右值参考参数,其中 A 是一个模板类型参数,可以绑定到任何种类的 A



无论 A 是否为左值,右值,const限定,volatile限定或非限定, A&& / code>可以绑定到该对象(再次,当且仅当 A 本身是模板参数)。



在您的示例中,我们进行调用:

  make_pair(s,7)

这里, s std类型的左值:: string 7 是类型 int 的右值。由于您没有为函数模板指定模板参数,因此会执行模板参数扣除以确定参数是什么。



要绑定 s ,一个左值, T&& ,编译器推导 T code> std :: string& ,产生 std :: string& &&&< / code>。没有引用引用,但是,这个双引用折叠成 std :: string& s 是一个匹配。



绑定 >到 U&&& :编译器可以推导 U int ,产生类型 int&&& 的参数,它成功绑定到 7 rvalue。



这些新的语言功能有很多细微之处,但如果你遵循一个简单的规则,很容易:


如果可以从函数参数中推导出模板参数,则可以推导出。不要显式提供参数,除非你绝对必须。



让编译器做艰苦的工作,99.9%的时间,它将是你想要的。当它不是你想要的,你通常会得到一个编译错误,很容易识别和修复。



I was just playing around with g++ 4.7 (one of the later snapshots) with -std=c++11 enabled. I tried to compile some of my existing code base and one case that failed somewhat confuses me.

I would appreciate if someone can explain what is going on.

Here's the code

#include <utility>
#include <iostream>
#include <vector>
#include <string>

int main ( )
{
    std::string s = "abc";

    // 1 ok
    std::pair < std::string, int > a = std::make_pair ( s, 7 );

    // 2 error on the next line
    std::pair < std::string, int > b = std::make_pair < std::string, int > ( s, 7 );

    // 3 ok
    std::pair < std::string, int > d = std::pair < std::string, int > ( s, 7 );

    return 0;
}

I understand that make_pair is meant to be used as the (1) case (if I specify the types, then I might as well use (3)), But I don't understand why it's failing in this case.

The exact error is:

test.cpp: In function ‘int main()’: test.cpp:11:83: error: no matching function for call to ‘make_pair(std::string&, int)’ test.cpp:11:83: note: candidate is: In file included from /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/utility:72:0, from test.cpp:1: /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:274:5: note: template constexpr std::pair::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&) /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:274:5: note: template argument deduction/substitution failed: test.cpp:11:83: note: cannot convert ‘s’ (type ‘std::string {aka std::basic_string}’) to type ‘std::basic_string&&’

Again, the question here is just "what's going on?" I know that I can fix the problem by removing the template specification, but I just want to know what's failing here under the covers. Thanks in advance.

EDIT:

  • g++ 4.4 compiles this code with no problems.
  • Removing -std=c++11 also compiles with code with no problems.

解决方案

This is not how std::make_pair is intended to be used; you are not supposed to explicitly specify the template arguments.

The C++11 std::make_pair takes two arguments, of type T&& and U&&, where T and U are template type parameters. Effectively, it looks like this (ignoring the return type):

template <typename T, typename U>
[return type] make_pair(T&& argT, U&& argU);

When you call std::make_pair and explicitly specify the template type arguments, no argument deduction takes place. Instead, the type arguments are substituted directly into the template declaration, yielding:

[return type] make_pair(std::string&& argT, int&& argU);

Note that both of these parameter types are rvalue references. Thus, they can only bind to rvalues. This isn't a problem for the second argument that you pass, 7, because that is an rvalue expression. s, however, is an lvalue expression (it isn't a temporary and it isn't being moved). This means the function template is not a match for your arguments, which is why you get the error.

So, why does it work when you don't explicitly specify what T and U are in the template argument list? In short, rvalue reference parameters are special in templates. Due in part to a language feature called reference collapsing, an rvalue reference parameter of type A&&, where A is a template type parameter, can bind to any kind of A.

It doesn't matter whether the A is an lvalue, an rvalue, const-qualified, volatile-qualified, or unqualified, an A&& can bind to that object (again, if and only if A is itself a template parameter).

In your example, we make the call:

make_pair(s, 7)

Here, s is an lvalue of type std::string and 7 is an rvalue of type int. Since you do not specify the template arguments for the function template, template argument deduction is performed to figure out what the arguments are.

To bind s, an lvalue, to T&&, the compiler deduces T to be std::string&, yielding an argument of type std::string& &&. There are no references to references, though, so this "double reference" collapses to become std::string&. s is a match.

It's simple to bind 7 to U&&: the compiler can deduce U to be int, yielding a parameter of type int&&, which binds successfully to 7 because it is an rvalue.

There are lots of subtleties with these new language features, but if you follow one simple rule, it's pretty easy:

If a template argument can be deduced from the function arguments, let it be deduced. Don't explicitly provide the argument unless you absolutely must.

Let the compiler do the hard work, and 99.9% of the time it'll be exactly what you wanted anyway. When it isn't what you wanted, you'll usually get a compilation error which is easy to identify and fix.

这篇关于C ++ 11 make_pair与指定的模板参数不编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆