c++ 奇怪的编译器错误:无法将参数从“int”转换为“int &&”

5q4ezhmt  于 2023-05-24  发布在  其他
关注(0)|答案(4)|浏览(347)

这到底是怎么回事
我试图创建一对intstring,如果我使用“魔术值”,但似乎不能传入变量,我可以创建这对。

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)代码中没有问题。
我觉得有点愚蠢,因为不能锻炼这里发生了什么,但我能说什么,我只是不明白。

2nc8po8w

2nc8po8w1#

Reference说:

template< class T1, class T2 >
std::pair<T1,T2> make_pair( T1 t, T2 u );           (until C++11)

template< class T1, class T2 >
std::pair<V1,V2> make_pair( T1&& t, T2&& u );       (since C++11)

请注意,返回类型不同。它还说:
推导出的类型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的构造函数:

num_text.push_back(std::make_pair(num, text));               // deduced type
num_text.push_back(std::pair<int, std::string>(num, text));  // specific type

编译错误的原因是您已经指定了int(作为T1)和std::string(作为T2)的类型,因此函数需要T1 &&T2 &&。参见this answer了解为什么这是一个问题。

fhg3lkii

fhg3lkii2#

make_pair<T1,T2>并不构成一对pair<T1,T2>类型,而是从其参数中推导出一对合适的引用类型,以允许完美转发。它被指定为

template <class T1, class T2>
pair<V1, V2> make_pair(T1&& x, T2&& y);

对于一些合适的参考类型V1V2。这只在参数类型被推导出来的情况下才起作用,这样&&就可以在必要时衰减为 lvalue 引用。通过显式指定模板参数,它们不再被推导,因此函数参数只能是 rvalues
解决方案是让编译器推导类型:

num_text.push_back(std::make_pair(42, std::string("Smeg")));  // Works fine
num_text.push_back(std::make_pair(42, text));                 // Works fine
num_text.push_back(std::make_pair(num, std::string("Smeg"))); // Works fine
num_text.push_back(std::make_pair(num, text));                // Works fine
num_text.push_back(std::make_pair(42, std::string("Smeg")));  // Works fine again

如果需要创建一个特定类型的对,不要使用make_pair,只需创建一个对

// Works, but perhaps with more copying than you want.
num_text.push_back(std::pair<int, std::string>(num, text));
kqlmhetl

kqlmhetl3#

make_pair通常在 * 不 * 显式指定模板参数的情况下使用。这就是它的用法:

num_text.push_back(std::make_pair(42, std::string("Smeg")));
num_text.push_back(std::make_pair(42, text));
num_text.push_back(std::make_pair(num, std::string("Smeg")));
num_text.push_back(std::make_pair(num, text));
num_text.push_back(std::make_pair(42, std::string("Smeg")));

或者,如果您需要确切的类型:

typedef decltype(num_text)::value_type value_type;
num_text.push_back(value_type(42, std::string("Smeg")));
num_text.push_back(value_type(42, text));
num_text.push_back(value_type(num, std::string("Smeg")));
num_text.push_back(value_type(num, text));
num_text.push_back(value_type(42, std::string("Smeg")));
1zmg4dgp

1zmg4dgp4#

现在,std::make_pair在C++标准中的定义如下

template <class T1, class T2>

见下文make_pair(**T1&&, T2&&**);
不使用std::make_pair也可以写得更简单
num_text.push_back( { 42, text } );

相关问题