这到底是怎么回事
我试图创建一对int
和string
,如果我使用“魔术值”,但似乎不能传入变量,我可以创建这对。
std::vector<std::pair<int, std::string> > num_text;
std::string text = "Smeg";
int num = 42;
// Works fine
num_text.push_back(std::make_pair<int, std::string>(42, std::string("Smeg")));
// Cannot convert parameter 2 from 'std::string' to 'std::string &&'
num_text.push_back(std::make_pair<int, std::string>(42, text));
// Cannot convert parameter 1 from 'int' to 'int &&'
num_text.push_back(std::make_pair<int, std::string>(num, std::string("Smeg")));
// Cannot convert parameter 1 from 'int' to 'int &&'
num_text.push_back(std::make_pair<int, std::string>(num, text));
// Works fine again
num_text.push_back(std::make_pair<int, std::string>(42, std::string("Smeg")));
我正在使用VS 2012,并粘贴了一些用VS 2008编写的代码。无法想象这与它有任何关系,但在原始(2008)代码中没有问题。
我觉得有点愚蠢,因为不能锻炼这里发生了什么,但我能说什么,我只是不明白。
4条答案
按热度按时间2nc8po8w1#
Reference说:
请注意,返回类型不同。它还说:
推导出的类型V1和V2是std::decay::type和std::decay::type(通常应用于通过值传递的函数的参数的类型转换),除非应用std::decay导致某些类型X的std::reference_wrapper,在这种情况下,推导出的类型是X&。
所以事实上,自2008年以来(我指的是Visual C++ 2008),函数
make_pair
的语义已经改变了。您可以从std::make_pair
中删除模板参数并让它推断类型,或者如果需要创建特定类型的对,则使用std::pair
的构造函数:编译错误的原因是您已经指定了
int
(作为T1
)和std::string
(作为T2
)的类型,因此函数需要T1 &&
和T2 &&
。参见this answer了解为什么这是一个问题。fhg3lkii2#
make_pair<T1,T2>
并不构成一对pair<T1,T2>
类型,而是从其参数中推导出一对合适的引用类型,以允许完美转发。它被指定为对于一些合适的参考类型
V1
和V2
。这只在参数类型被推导出来的情况下才起作用,这样&&
就可以在必要时衰减为 lvalue 引用。通过显式指定模板参数,它们不再被推导,因此函数参数只能是 rvalues。解决方案是让编译器推导类型:
如果需要创建一个特定类型的对,不要使用
make_pair
,只需创建一个对kqlmhetl3#
make_pair
通常在 * 不 * 显式指定模板参数的情况下使用。这就是它的用法:或者,如果您需要确切的类型:
1zmg4dgp4#
现在,
std::make_pair
在C++标准中的定义如下见下文
make_pair(**T1&&, T2&&**);
不使用
std::make_pair
也可以写得更简单num_text.push_back( { 42, text } );
。